DimensionGenerator.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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. zm.messungEnde();
  211. blockGenTime += zm.getSekunden();
  212. }
  213. if (generated.isA())
  214. chunk->putBlockAt(
  215. Framework::Vec3<int>(
  216. x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z),
  217. generated);
  218. else
  219. chunk->putBlockTypeAt(
  220. Framework::Vec3<int>(
  221. x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z),
  222. generated);
  223. }
  224. }
  225. }
  226. caveGen->release();
  227. structures->release();
  228. zmGlobal.messungEnde();
  229. std::cout << "structureTime: " << structureTime << "\n";
  230. std::cout << "caveTime: " << caveTime << "\n";
  231. std::cout << "blockGenTime: " << blockGenTime << "\n";
  232. std::cout << "biomTime: " << biomTime << "\n";
  233. std::cout << "heightTime: " << heightTime << "\n";
  234. std::cout << "totalTime: " << zmGlobal.getSekunden() << "\n";
  235. return chunk;
  236. }
  237. Framework::Either<Block*, int> DimensionGenerator::generateBlock(
  238. Framework::Vec3<int> location)
  239. {
  240. Framework::RCArray<GeneratedStructure>* structures
  241. = getGeneratedStructoresForArea(location, location);
  242. BiomGenerator* biom = zBiomGenerator(location.x, location.y);
  243. // TODO: use Noise interpolator for height map between different bioms
  244. int height = MIN_AIR_LEVEL
  245. + (int)(biom->zHeightMapNoise()->getNoise(
  246. (double)(location.x), (double)(location.y), 0.0)
  247. * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
  248. int maxSurfaceHeight
  249. = (int)(MAX_SURFACE_HEIGHT
  250. * (1.f
  251. - (float)(height - MIN_AIR_LEVEL)
  252. / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
  253. int actualSurfaceHeight
  254. = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
  255. + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
  256. * (float)biom->zHeightMapNoise()->getNoise(
  257. (double)(location.x), (double)(location.y), 10.0)));
  258. for (auto structure : *structures)
  259. {
  260. if (structure->isBlockAffected(location))
  261. {
  262. auto generated = structure->generateBlockAt(location);
  263. structures->release();
  264. return generated;
  265. }
  266. }
  267. structures->release();
  268. if (location.z < height && location.z >= height - actualSurfaceHeight)
  269. return biom->generateSurfaceBlock(location.x, location.y, location.z);
  270. else if (location.z < height)
  271. return biom->generateBelowSurfaceBlock(
  272. location.x, location.y, location.z);
  273. return BlockTypeEnum::AIR;
  274. }
  275. bool DimensionGenerator::spawnStructure(Framework::Vec3<int> location,
  276. std::function<bool(GenerationTemplate* tmpl)> filter)
  277. {
  278. BiomGenerator* biom = zBiomGenerator(location.x, location.y);
  279. for (auto t : biom->getTemplates())
  280. {
  281. if (filter(t))
  282. {
  283. RandNoise noise((int)time(0));
  284. GeneratedStructure* genStr
  285. = t->generateAt(location, &noise, dimensionId);
  286. if (genStr)
  287. {
  288. int minSearchX = location.x + t->getMinAffectedOffset().x;
  289. int minSearchY = location.y + t->getMinAffectedOffset().y;
  290. int minSearchZ
  291. = MAX(location.z + t->getMinAffectedOffset().z, 0);
  292. int maxSearchX = location.x + t->getMaxAffectedOffset().x;
  293. int maxSearchY = location.y + t->getMaxAffectedOffset().y;
  294. int maxSearchZ = MIN(
  295. location.z + t->getMaxAffectedOffset().z, WORLD_HEIGHT - 1);
  296. for (int x = minSearchX; x <= maxSearchX; x++)
  297. {
  298. for (int y = minSearchY; y <= maxSearchY; y++)
  299. {
  300. for (int z = minSearchZ; z <= maxSearchZ; z++)
  301. {
  302. if (genStr->isBlockAffected(
  303. Framework::Vec3<int>(x, y, z)))
  304. {
  305. auto gen = genStr->generateBlockAt(
  306. Framework::Vec3<int>(x, y, z));
  307. Game::INSTANCE->zDimension(dimensionId)
  308. ->placeBlock(
  309. Framework::Vec3<int>(x, y, z), gen);
  310. }
  311. }
  312. }
  313. }
  314. genStr->release();
  315. return 1;
  316. }
  317. }
  318. }
  319. return 0;
  320. }
  321. int DimensionGenerator::getDimensionId() const
  322. {
  323. return dimensionId;
  324. }