mg_biome.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. Minetest
  3. Copyright (C) 2014-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  4. Copyright (C) 2014-2018 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 "mg_biome.h"
  18. #include "mg_decoration.h"
  19. #include "emerge.h"
  20. #include "server.h"
  21. #include "nodedef.h"
  22. #include "map.h" //for MMVManip
  23. #include "util/numeric.h"
  24. #include "porting.h"
  25. #include "settings.h"
  26. ///////////////////////////////////////////////////////////////////////////////
  27. BiomeManager::BiomeManager(Server *server) :
  28. ObjDefManager(server, OBJDEF_BIOME)
  29. {
  30. m_server = server;
  31. // Create default biome to be used in case none exist
  32. Biome *b = new Biome;
  33. b->name = "default";
  34. b->flags = 0;
  35. b->depth_top = 0;
  36. b->depth_filler = -MAX_MAP_GENERATION_LIMIT;
  37. b->depth_water_top = 0;
  38. b->depth_riverbed = 0;
  39. b->min_pos = v3s16(-MAX_MAP_GENERATION_LIMIT,
  40. -MAX_MAP_GENERATION_LIMIT, -MAX_MAP_GENERATION_LIMIT);
  41. b->max_pos = v3s16(MAX_MAP_GENERATION_LIMIT,
  42. MAX_MAP_GENERATION_LIMIT, MAX_MAP_GENERATION_LIMIT);
  43. b->heat_point = 0.0;
  44. b->humidity_point = 0.0;
  45. b->vertical_blend = 0;
  46. b->m_nodenames.emplace_back("mapgen_stone");
  47. b->m_nodenames.emplace_back("mapgen_stone");
  48. b->m_nodenames.emplace_back("mapgen_stone");
  49. b->m_nodenames.emplace_back("mapgen_water_source");
  50. b->m_nodenames.emplace_back("mapgen_water_source");
  51. b->m_nodenames.emplace_back("mapgen_river_water_source");
  52. b->m_nodenames.emplace_back("mapgen_stone");
  53. b->m_nodenames.emplace_back("ignore");
  54. b->m_nodenames.emplace_back("ignore");
  55. b->m_nnlistsizes.push_back(1);
  56. b->m_nodenames.emplace_back("ignore");
  57. b->m_nodenames.emplace_back("ignore");
  58. b->m_nodenames.emplace_back("ignore");
  59. m_ndef->pendNodeResolve(b);
  60. add(b);
  61. }
  62. void BiomeManager::clear()
  63. {
  64. EmergeManager *emerge = m_server->getEmergeManager();
  65. // Remove all dangling references in Decorations
  66. DecorationManager *decomgr = emerge->getWritableDecorationManager();
  67. for (size_t i = 0; i != decomgr->getNumObjects(); i++) {
  68. Decoration *deco = (Decoration *)decomgr->getRaw(i);
  69. deco->biomes.clear();
  70. }
  71. // Don't delete the first biome
  72. for (size_t i = 1; i < m_objects.size(); i++)
  73. delete (Biome *)m_objects[i];
  74. m_objects.resize(1);
  75. }
  76. BiomeManager *BiomeManager::clone() const
  77. {
  78. auto mgr = new BiomeManager();
  79. assert(mgr);
  80. ObjDefManager::cloneTo(mgr);
  81. mgr->m_server = m_server;
  82. return mgr;
  83. }
  84. ////////////////////////////////////////////////////////////////////////////////
  85. void BiomeParamsOriginal::readParams(const Settings *settings)
  86. {
  87. settings->getNoiseParams("mg_biome_np_heat", np_heat);
  88. settings->getNoiseParams("mg_biome_np_heat_blend", np_heat_blend);
  89. settings->getNoiseParams("mg_biome_np_humidity", np_humidity);
  90. settings->getNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend);
  91. }
  92. void BiomeParamsOriginal::writeParams(Settings *settings) const
  93. {
  94. settings->setNoiseParams("mg_biome_np_heat", np_heat);
  95. settings->setNoiseParams("mg_biome_np_heat_blend", np_heat_blend);
  96. settings->setNoiseParams("mg_biome_np_humidity", np_humidity);
  97. settings->setNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend);
  98. }
  99. ////////////////////////////////////////////////////////////////////////////////
  100. BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr,
  101. const BiomeParamsOriginal *params, v3s16 chunksize)
  102. {
  103. m_bmgr = biomemgr;
  104. m_params = params;
  105. m_csize = chunksize;
  106. noise_heat = new Noise(&params->np_heat,
  107. params->seed, m_csize.X, m_csize.Z);
  108. noise_humidity = new Noise(&params->np_humidity,
  109. params->seed, m_csize.X, m_csize.Z);
  110. noise_heat_blend = new Noise(&params->np_heat_blend,
  111. params->seed, m_csize.X, m_csize.Z);
  112. noise_humidity_blend = new Noise(&params->np_humidity_blend,
  113. params->seed, m_csize.X, m_csize.Z);
  114. heatmap = noise_heat->result;
  115. humidmap = noise_humidity->result;
  116. biomemap = new biome_t[m_csize.X * m_csize.Z];
  117. // Initialise with the ID of 'BIOME_NONE' so that cavegen can get the
  118. // fallback biome when biome generation (which calculates the biomemap IDs)
  119. // is disabled.
  120. memset(biomemap, 0, sizeof(biome_t) * m_csize.X * m_csize.Z);
  121. }
  122. BiomeGenOriginal::~BiomeGenOriginal()
  123. {
  124. delete []biomemap;
  125. delete noise_heat;
  126. delete noise_humidity;
  127. delete noise_heat_blend;
  128. delete noise_humidity_blend;
  129. }
  130. BiomeGen *BiomeGenOriginal::clone(BiomeManager *biomemgr) const
  131. {
  132. return new BiomeGenOriginal(biomemgr, m_params, m_csize);
  133. }
  134. float BiomeGenOriginal::calcHeatAtPoint(v3s16 pos) const
  135. {
  136. return NoisePerlin2D(&m_params->np_heat, pos.X, pos.Z, m_params->seed) +
  137. NoisePerlin2D(&m_params->np_heat_blend, pos.X, pos.Z, m_params->seed);
  138. }
  139. float BiomeGenOriginal::calcHumidityAtPoint(v3s16 pos) const
  140. {
  141. return NoisePerlin2D(&m_params->np_humidity, pos.X, pos.Z, m_params->seed) +
  142. NoisePerlin2D(&m_params->np_humidity_blend, pos.X, pos.Z, m_params->seed);
  143. }
  144. Biome *BiomeGenOriginal::calcBiomeAtPoint(v3s16 pos) const
  145. {
  146. return calcBiomeFromNoise(calcHeatAtPoint(pos), calcHumidityAtPoint(pos), pos);
  147. }
  148. void BiomeGenOriginal::calcBiomeNoise(v3s16 pmin)
  149. {
  150. m_pmin = pmin;
  151. noise_heat->perlinMap2D(pmin.X, pmin.Z);
  152. noise_humidity->perlinMap2D(pmin.X, pmin.Z);
  153. noise_heat_blend->perlinMap2D(pmin.X, pmin.Z);
  154. noise_humidity_blend->perlinMap2D(pmin.X, pmin.Z);
  155. for (s32 i = 0; i < m_csize.X * m_csize.Z; i++) {
  156. noise_heat->result[i] += noise_heat_blend->result[i];
  157. noise_humidity->result[i] += noise_humidity_blend->result[i];
  158. }
  159. }
  160. biome_t *BiomeGenOriginal::getBiomes(s16 *heightmap, v3s16 pmin)
  161. {
  162. for (s16 zr = 0; zr < m_csize.Z; zr++)
  163. for (s16 xr = 0; xr < m_csize.X; xr++) {
  164. s32 i = zr * m_csize.X + xr;
  165. Biome *biome = calcBiomeFromNoise(
  166. noise_heat->result[i],
  167. noise_humidity->result[i],
  168. v3s16(pmin.X + xr, heightmap[i], pmin.Z + zr));
  169. biomemap[i] = biome->index;
  170. }
  171. return biomemap;
  172. }
  173. Biome *BiomeGenOriginal::getBiomeAtPoint(v3s16 pos) const
  174. {
  175. return getBiomeAtIndex(
  176. (pos.Z - m_pmin.Z) * m_csize.X + (pos.X - m_pmin.X),
  177. pos);
  178. }
  179. Biome *BiomeGenOriginal::getBiomeAtIndex(size_t index, v3s16 pos) const
  180. {
  181. return calcBiomeFromNoise(
  182. noise_heat->result[index],
  183. noise_humidity->result[index],
  184. pos);
  185. }
  186. Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, v3s16 pos) const
  187. {
  188. Biome *biome_closest = nullptr;
  189. Biome *biome_closest_blend = nullptr;
  190. float dist_min = FLT_MAX;
  191. float dist_min_blend = FLT_MAX;
  192. for (size_t i = 1; i < m_bmgr->getNumObjects(); i++) {
  193. Biome *b = (Biome *)m_bmgr->getRaw(i);
  194. if (!b ||
  195. pos.Y < b->min_pos.Y || pos.Y > b->max_pos.Y + b->vertical_blend ||
  196. pos.X < b->min_pos.X || pos.X > b->max_pos.X ||
  197. pos.Z < b->min_pos.Z || pos.Z > b->max_pos.Z)
  198. continue;
  199. float d_heat = heat - b->heat_point;
  200. float d_humidity = humidity - b->humidity_point;
  201. float dist = (d_heat * d_heat) + (d_humidity * d_humidity);
  202. if (pos.Y <= b->max_pos.Y) { // Within y limits of biome b
  203. if (dist < dist_min) {
  204. dist_min = dist;
  205. biome_closest = b;
  206. }
  207. } else if (dist < dist_min_blend) { // Blend area above biome b
  208. dist_min_blend = dist;
  209. biome_closest_blend = b;
  210. }
  211. }
  212. // Carefully tune pseudorandom seed variation to avoid single node dither
  213. // and create larger scale blending patterns similar to horizontal biome
  214. // blend.
  215. const u64 seed = pos.Y + (heat + humidity) * 0.9f;
  216. PcgRandom rng(seed);
  217. if (biome_closest_blend && dist_min_blend <= dist_min &&
  218. rng.range(0, biome_closest_blend->vertical_blend) >=
  219. pos.Y - biome_closest_blend->max_pos.Y)
  220. return biome_closest_blend;
  221. return (biome_closest) ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE);
  222. }
  223. ////////////////////////////////////////////////////////////////////////////////
  224. ObjDef *Biome::clone() const
  225. {
  226. auto obj = new Biome();
  227. ObjDef::cloneTo(obj);
  228. NodeResolver::cloneTo(obj);
  229. obj->flags = flags;
  230. obj->c_top = c_top;
  231. obj->c_filler = c_filler;
  232. obj->c_stone = c_stone;
  233. obj->c_water_top = c_water_top;
  234. obj->c_water = c_water;
  235. obj->c_river_water = c_river_water;
  236. obj->c_riverbed = c_riverbed;
  237. obj->c_dust = c_dust;
  238. obj->c_cave_liquid = c_cave_liquid;
  239. obj->c_dungeon = c_dungeon;
  240. obj->c_dungeon_alt = c_dungeon_alt;
  241. obj->c_dungeon_stair = c_dungeon_stair;
  242. obj->depth_top = depth_top;
  243. obj->depth_filler = depth_filler;
  244. obj->depth_water_top = depth_water_top;
  245. obj->depth_riverbed = depth_riverbed;
  246. obj->min_pos = min_pos;
  247. obj->max_pos = max_pos;
  248. obj->heat_point = heat_point;
  249. obj->humidity_point = humidity_point;
  250. obj->vertical_blend = vertical_blend;
  251. return obj;
  252. }
  253. void Biome::resolveNodeNames()
  254. {
  255. getIdFromNrBacklog(&c_top, "mapgen_stone", CONTENT_AIR, false);
  256. getIdFromNrBacklog(&c_filler, "mapgen_stone", CONTENT_AIR, false);
  257. getIdFromNrBacklog(&c_stone, "mapgen_stone", CONTENT_AIR, false);
  258. getIdFromNrBacklog(&c_water_top, "mapgen_water_source", CONTENT_AIR, false);
  259. getIdFromNrBacklog(&c_water, "mapgen_water_source", CONTENT_AIR, false);
  260. getIdFromNrBacklog(&c_river_water, "mapgen_river_water_source", CONTENT_AIR, false);
  261. getIdFromNrBacklog(&c_riverbed, "mapgen_stone", CONTENT_AIR, false);
  262. getIdFromNrBacklog(&c_dust, "ignore", CONTENT_IGNORE, false);
  263. getIdsFromNrBacklog(&c_cave_liquid);
  264. getIdFromNrBacklog(&c_dungeon, "ignore", CONTENT_IGNORE, false);
  265. getIdFromNrBacklog(&c_dungeon_alt, "ignore", CONTENT_IGNORE, false);
  266. getIdFromNrBacklog(&c_dungeon_stair, "ignore", CONTENT_IGNORE, false);
  267. }