DimensionGenerator.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #include "DimensionGenerator.h"
  2. #include <iostream>
  3. #include "Constants.h"
  4. #include "Game.h"
  5. #include "NoBlock.h"
  6. #include "Noise.h"
  7. #include "RandNoise.h"
  8. DimensionGenerator::DimensionGenerator(
  9. int dimensionId, CaveGenerator* caveGenerator)
  10. : ReferenceCounter(),
  11. dimensionId(dimensionId),
  12. minTemplateAffectedPosition(0, 0, 0),
  13. maxTemplateAffectedPosition(0, 0, 0),
  14. caveGenerator(caveGenerator)
  15. {
  16. StaticRegistry<DimensionGenerator>::INSTANCE.registerT(this, dimensionId);
  17. }
  18. DimensionGenerator::~DimensionGenerator() {}
  19. void DimensionGenerator::initialize(int seed)
  20. {
  21. this->seed = seed + dimensionId;
  22. caveGenerator->initialize(this->seed);
  23. for (auto biomGen : biomGenerators)
  24. {
  25. biomGen->setSeed(this->seed);
  26. }
  27. }
  28. BiomGenerator* DimensionGenerator::zBiomGenerator(int x, int y)
  29. {
  30. double noise = zBiomNoise()->getNoise((double)x, (double)y, 0.0);
  31. double border = 0;
  32. BiomGenerator* gen = 0;
  33. auto genI = biomGenerators.begin();
  34. auto distI = biomDistribution.begin();
  35. do
  36. {
  37. border += (double)distI++;
  38. gen = genI++;
  39. } while (border < noise && (bool)distI && (bool)genI);
  40. return gen;
  41. }
  42. void DimensionGenerator::registerBiom(
  43. BiomGenerator* generator, double possibility)
  44. {
  45. biomGenerators.add(generator);
  46. biomDistribution.add(possibility);
  47. for (auto t : generator->getTemplates())
  48. {
  49. minTemplateAffectedPosition.x
  50. = MIN(minTemplateAffectedPosition.x, t->getMinAffectedOffset().x);
  51. minTemplateAffectedPosition.y
  52. = MIN(minTemplateAffectedPosition.y, t->getMinAffectedOffset().y);
  53. minTemplateAffectedPosition.z
  54. = MIN(minTemplateAffectedPosition.z, t->getMinAffectedOffset().z);
  55. maxTemplateAffectedPosition.x
  56. = MAX(maxTemplateAffectedPosition.x, t->getMaxAffectedOffset().x);
  57. maxTemplateAffectedPosition.y
  58. = MAX(maxTemplateAffectedPosition.y, t->getMaxAffectedOffset().y);
  59. maxTemplateAffectedPosition.z
  60. = MAX(maxTemplateAffectedPosition.z, t->getMaxAffectedOffset().z);
  61. }
  62. generator->setSeed(seed);
  63. }
  64. Framework::RCArray<GeneratedStructure>*
  65. DimensionGenerator::getGeneratedStructoresForArea(
  66. Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos)
  67. {
  68. Framework::RCArray<GeneratedStructure>* result
  69. = new Framework::RCArray<GeneratedStructure>();
  70. int minSearchX = minPos.x - maxTemplateAffectedPosition.x;
  71. int minSearchY = minPos.y - maxTemplateAffectedPosition.y;
  72. int minSearchZ = MAX(minPos.z - maxTemplateAffectedPosition.z, 0);
  73. int maxSearchX = maxPos.x - minTemplateAffectedPosition.x;
  74. int maxSearchY = maxPos.y - minTemplateAffectedPosition.y;
  75. int maxSearchZ
  76. = MIN(maxPos.z - minTemplateAffectedPosition.z, WORLD_HEIGHT - 1);
  77. Noise* structureNoise = zStructureNoise();
  78. for (int x = minSearchX; x <= maxSearchX; x++)
  79. {
  80. for (int y = minSearchY; y <= maxSearchY; y++)
  81. {
  82. BiomGenerator* biom = zBiomGenerator(x, y);
  83. int height = MIN_AIR_LEVEL
  84. + (int)(biom->zHeightMapNoise()->getNoise(
  85. (double)(x), (double)(y), 0.0)
  86. * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
  87. for (int z = minSearchZ; z <= maxSearchZ; z++)
  88. {
  89. if (z < height)
  90. {
  91. double rValue = structureNoise->getNoise(
  92. (double)x, (double)y, (double)z);
  93. double probSum = 0;
  94. for (auto t : biom->getTemplates())
  95. {
  96. if (t->isGenerationPossable(
  97. Framework::Vec3<int>(x, y, z), height - z))
  98. {
  99. if (rValue - probSum <= t->getPropability())
  100. {
  101. result->add(
  102. t->generateAt(Framework::Vec3<int>(x, y, z),
  103. structureNoise,
  104. dimensionId));
  105. break;
  106. }
  107. }
  108. probSum += t->getPropability();
  109. }
  110. }
  111. }
  112. }
  113. }
  114. return result;
  115. }
  116. Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
  117. {
  118. std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
  119. double structureTime = 0;
  120. double caveTime = 0;
  121. double blockGenTime = 0;
  122. double biomTime = 0;
  123. double heightTime = 0;
  124. ZeitMesser zm;
  125. ZeitMesser zmGlobal;
  126. zm.messungStart();
  127. zmGlobal.messungStart();
  128. Framework::RCArray<GeneratedStructure>* structures
  129. = getGeneratedStructoresForArea(
  130. Framework::Vec3<int>(
  131. centerX - CHUNK_SIZE / 2, centerY - CHUNK_SIZE / 2, 0),
  132. Framework::Vec3<int>(centerX + CHUNK_SIZE / 2,
  133. centerY + CHUNK_SIZE / 2,
  134. WORLD_HEIGHT - 1));
  135. zm.messungEnde();
  136. structureTime += zm.getSekunden();
  137. zm.messungStart();
  138. CaveChunkGenerator* caveGen
  139. = caveGenerator->getGeneratorForChunk(centerX, centerY);
  140. zm.messungEnde();
  141. caveTime += zm.getSekunden();
  142. Chunk* chunk = new Chunk(Framework::Punkt(centerX, centerY), dimensionId);
  143. for (int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++)
  144. {
  145. for (int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++)
  146. {
  147. zm.messungStart();
  148. BiomGenerator* biom = zBiomGenerator(x + centerX, y + centerY);
  149. zm.messungEnde();
  150. biomTime += zm.getSekunden();
  151. // TODO: use Noise interpolator for height map between different
  152. // bioms
  153. zm.messungStart();
  154. int height
  155. = MIN_AIR_LEVEL
  156. + (int)(biom->zHeightMapNoise()->getNoise(
  157. (double)(x + centerX), (double)(y + centerY), 0.0)
  158. * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
  159. int maxSurfaceHeight
  160. = (int)(MAX_SURFACE_HEIGHT
  161. * (1.f
  162. - (float)(height - MIN_AIR_LEVEL)
  163. / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
  164. int actualSurfaceHeight
  165. = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
  166. + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
  167. * (float)biom->zHeightMapNoise()->getNoise(
  168. (double)(x + centerX),
  169. (double)(y + centerY),
  170. 10.0)));
  171. zm.messungEnde();
  172. heightTime += zm.getSekunden();
  173. for (int z = 0; z < WORLD_HEIGHT; z++)
  174. {
  175. Framework::Either<Block*, int> generated = BlockTypeEnum::AIR;
  176. bool structureAffected = 0;
  177. for (auto structure : *structures)
  178. {
  179. zm.messungStart();
  180. if (structure->isBlockAffected(
  181. Framework::Vec3<int>(x + centerX, y + centerY, z)))
  182. {
  183. generated = structure->generateBlockAt(
  184. Framework::Vec3<int>(x + centerX, y + centerY, z));
  185. structureAffected = 1;
  186. zm.messungEnde();
  187. structureTime += zm.getSekunden();
  188. break;
  189. }
  190. zm.messungEnde();
  191. structureTime += zm.getSekunden();
  192. }
  193. if (!structureAffected)
  194. {
  195. zm.messungStart();
  196. bool inCave
  197. = caveGen->isInCave(x + centerX, y + centerY, z);
  198. zm.messungEnde();
  199. caveTime += zm.getSekunden();
  200. zm.messungStart();
  201. if (inCave)
  202. generated = biom->generateCaveBlock(
  203. x + centerX, y + centerY, z);
  204. else if (z < height && z >= height - actualSurfaceHeight)
  205. generated = biom->generateSurfaceBlock(
  206. x + centerX, y + centerY, z);
  207. else if (z < height)
  208. generated = biom->generateBelowSurfaceBlock(
  209. x + centerX, y + centerY, z);
  210. else if (z >= height)
  211. {
  212. generated = biom->generateAboveSurfaceBlock(
  213. x + centerX, y + centerY, z, height);
  214. }
  215. zm.messungEnde();
  216. blockGenTime += zm.getSekunden();
  217. }
  218. if (generated.isA())
  219. chunk->putBlockAt(
  220. Framework::Vec3<int>(
  221. x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z),
  222. generated);
  223. else
  224. chunk->putBlockTypeAt(
  225. Framework::Vec3<int>(
  226. x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z),
  227. generated);
  228. }
  229. }
  230. }
  231. caveGen->release();
  232. structures->release();
  233. zmGlobal.messungEnde();
  234. std::cout << "structureTime: " << structureTime << "\n";
  235. std::cout << "caveTime: " << caveTime << "\n";
  236. std::cout << "blockGenTime: " << blockGenTime << "\n";
  237. std::cout << "biomTime: " << biomTime << "\n";
  238. std::cout << "heightTime: " << heightTime << "\n";
  239. std::cout << "totalTime: " << zmGlobal.getSekunden() << "\n";
  240. return chunk;
  241. }
  242. Framework::Either<Block*, int> DimensionGenerator::generateBlock(
  243. Framework::Vec3<int> location)
  244. {
  245. Framework::RCArray<GeneratedStructure>* structures
  246. = getGeneratedStructoresForArea(location, location);
  247. BiomGenerator* biom = zBiomGenerator(location.x, location.y);
  248. // TODO: use Noise interpolator for height map between different bioms
  249. int height = MIN_AIR_LEVEL
  250. + (int)(biom->zHeightMapNoise()->getNoise(
  251. (double)(location.x), (double)(location.y), 0.0)
  252. * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
  253. int maxSurfaceHeight
  254. = (int)(MAX_SURFACE_HEIGHT
  255. * (1.f
  256. - (float)(height - MIN_AIR_LEVEL)
  257. / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
  258. int actualSurfaceHeight
  259. = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
  260. + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
  261. * (float)biom->zHeightMapNoise()->getNoise(
  262. (double)(location.x), (double)(location.y), 10.0)));
  263. for (auto structure : *structures)
  264. {
  265. if (structure->isBlockAffected(location))
  266. {
  267. auto generated = structure->generateBlockAt(location);
  268. structures->release();
  269. return generated;
  270. }
  271. }
  272. structures->release();
  273. if (location.z < height && location.z >= height - actualSurfaceHeight)
  274. return biom->generateSurfaceBlock(location.x, location.y, location.z);
  275. else if (location.z < height)
  276. return biom->generateBelowSurfaceBlock(
  277. location.x, location.y, location.z);
  278. if (location.z >= height)
  279. {
  280. return biom->generateAboveSurfaceBlock(
  281. location.x, location.x, location.z, height);
  282. }
  283. return BlockTypeEnum::AIR;
  284. }
  285. bool DimensionGenerator::spawnStructure(Framework::Vec3<int> location,
  286. std::function<bool(GenerationTemplate* tmpl)> filter)
  287. {
  288. BiomGenerator* biom = zBiomGenerator(location.x, location.y);
  289. for (auto t : biom->getTemplates())
  290. {
  291. if (filter(t))
  292. {
  293. RandNoise noise((int)time(0));
  294. GeneratedStructure* genStr
  295. = t->generateAt(location, &noise, dimensionId);
  296. if (genStr)
  297. {
  298. int minSearchX = location.x + t->getMinAffectedOffset().x;
  299. int minSearchY = location.y + t->getMinAffectedOffset().y;
  300. int minSearchZ
  301. = MAX(location.z + t->getMinAffectedOffset().z, 0);
  302. int maxSearchX = location.x + t->getMaxAffectedOffset().x;
  303. int maxSearchY = location.y + t->getMaxAffectedOffset().y;
  304. int maxSearchZ = MIN(
  305. location.z + t->getMaxAffectedOffset().z, WORLD_HEIGHT - 1);
  306. for (int x = minSearchX; x <= maxSearchX; x++)
  307. {
  308. for (int y = minSearchY; y <= maxSearchY; y++)
  309. {
  310. for (int z = minSearchZ; z <= maxSearchZ; z++)
  311. {
  312. if (genStr->isBlockAffected(
  313. Framework::Vec3<int>(x, y, z)))
  314. {
  315. auto gen = genStr->generateBlockAt(
  316. Framework::Vec3<int>(x, y, z));
  317. Game::INSTANCE->zDimension(dimensionId)
  318. ->placeBlock(
  319. Framework::Vec3<int>(x, y, z), gen);
  320. }
  321. }
  322. }
  323. }
  324. genStr->release();
  325. return 1;
  326. }
  327. }
  328. }
  329. return 0;
  330. }
  331. int DimensionGenerator::getDimensionId() const
  332. {
  333. return dimensionId;
  334. }