WormCaveGenerator.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include "WormCaveGenerator.h"
  2. #include "Game.h"
  3. #include "FastNoiseWrapper.h"
  4. #include "RandNoise.h"
  5. NoiseWorm3D::NoiseWorm3D(Noise* pitch, Noise* yaw, Noise* size, Framework::Vec3<int> startPos, int distant, int minRad, int maxRad)
  6. : ReferenceCounter(),
  7. startChunk(Game::INSTANCE->getChunkCenter(startPos.x, startPos.y))
  8. {
  9. Vec3<float> lastPos = (Vec3<float>)startPos;
  10. keyPoints.add(lastPos);
  11. this->size.add((float)minRad);
  12. minAffected.x = (int)lastPos.x - minRad;
  13. minAffected.y = (int)lastPos.y - minRad;
  14. maxAffected.x = (int)lastPos.x + minRad;
  15. maxAffected.y = (int)lastPos.y + minRad;
  16. while (keyPoints.getEintragAnzahl() < distant * 20)
  17. {
  18. Vec3<float> defaultDir(1.f, 0.f, 0.f);
  19. if (keyPoints.getEintragAnzahl() > 1)
  20. {
  21. defaultDir = keyPoints.get(keyPoints.getEintragAnzahl() - 1) - keyPoints.get(keyPoints.getEintragAnzahl() - 2);
  22. }
  23. float n = (float)yaw->getNoise(lastPos.x, lastPos.y, lastPos.z);
  24. defaultDir.rotateZ((n - 0.5) / 2.f);
  25. defaultDir.normalize();
  26. n = (float)pitch->getNoise(lastPos.x, lastPos.y, lastPos.z);
  27. defaultDir.z = ((float)n - 0.3f) * 2.f;
  28. lastPos = lastPos + defaultDir;
  29. if ((Vec2<float>(lastPos.x, lastPos.y) - (Vec2<float>((float)startPos.x, (float)startPos.y))).getLengthSq() >= distant * distant)
  30. break;
  31. keyPoints.add(lastPos);
  32. float rad = (float)size->getNoise(lastPos.x, lastPos.y, lastPos.z) * (float)(maxRad - minRad) + (float)minRad;
  33. this->size.add(rad);
  34. minAffected.x = MIN(minAffected.x, (int)(lastPos.x - rad));
  35. minAffected.y = MIN(minAffected.y, (int)(lastPos.y - rad));
  36. maxAffected.x = MAX(maxAffected.x, (int)(lastPos.x + rad));
  37. maxAffected.y = MAX(maxAffected.y, (int)(lastPos.y + rad));
  38. }
  39. }
  40. Framework::Punkt NoiseWorm3D::getStartChunkCenter()
  41. {
  42. return startChunk;
  43. }
  44. bool NoiseWorm3D::isChunkAffected(int x, int y)
  45. {
  46. return x - CHUNK_SIZE / 2 <= maxAffected.x && x + CHUNK_SIZE / 2 >= minAffected.x && y - CHUNK_SIZE / 2 <= maxAffected.y && y + CHUNK_SIZE / 2 >= minAffected.y;
  47. }
  48. bool NoiseWorm3D::isInside(int x, int y, int z)
  49. {
  50. auto pi = keyPoints.begin();
  51. auto si = size.begin();
  52. while (pi && si)
  53. {
  54. if (Vec3<float>((float)x, (float)y, (float)z).abstand(pi.val()) < si.val())
  55. return 1;
  56. ++pi;
  57. ++si;
  58. }
  59. return 0;
  60. }
  61. WormCaveChunkGenerator::WormCaveChunkGenerator(Framework::RCArray<NoiseWorm3D> worms)
  62. : CaveChunkGenerator(),
  63. worms(worms)
  64. {}
  65. bool WormCaveChunkGenerator::isInCave(int x, int y, int z)
  66. {
  67. for (NoiseWorm3D* w : worms)
  68. {
  69. if (w->isInside(x, y, z))
  70. return 1;
  71. }
  72. return 0;
  73. }
  74. WormCaveGenerator::WormCaveGenerator(int minDistant, int maxDistant, int minRadius, int maxRadius, float cavePosibillityPerChunk)
  75. : CaveGenerator(),
  76. maxDistant(maxDistant),
  77. minDistant(minDistant),
  78. maxRadius(maxRadius),
  79. minRadius(minRadius),
  80. cavePosibillity(cavePosibillityPerChunk)
  81. {}
  82. WormCaveGenerator::~WormCaveGenerator()
  83. {
  84. wormStartNoise->release();
  85. }
  86. NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
  87. {
  88. for (NoiseWorm3D* worm : cache)
  89. {
  90. if (worm->getStartChunkCenter().x == x && worm->getStartChunkCenter().y == y)
  91. {
  92. return worm;
  93. }
  94. }
  95. for (Punkt p : noWormChunks)
  96. {
  97. if (p.x == x && p.y == y)
  98. return 0;
  99. }
  100. float cNoise = wormStartNoise->getNoise(x, y, 0);
  101. if (cNoise < cavePosibillity)
  102. {
  103. FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
  104. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  105. noise->SetFrequency(0.05f);
  106. FastNoiseWrapper* pitch = new FastNoiseWrapper(noise, seed + x * y + y + x);
  107. noise = new FastNoiseLite(seed + x * y + y + x);
  108. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  109. noise->SetFrequency(0.005f);
  110. FastNoiseWrapper* yaw = new FastNoiseWrapper(noise, seed - x * y - y - x);
  111. Vec3<int> start((int)(cNoise / cavePosibillity * CHUNK_SIZE) + x - CHUNK_SIZE / 2, (int)(cNoise / cavePosibillity * CHUNK_SIZE) + y - CHUNK_SIZE / 2, (int)(cNoise / cavePosibillity * 200));
  112. noise = new FastNoiseLite(seed + x * y - y + x);
  113. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  114. noise->SetFrequency(0.05f);
  115. FastNoiseWrapper* size = new FastNoiseWrapper(noise, seed + start.getLengthSq() + start.x + start.y + start.z);
  116. NoiseWorm3D* worm = new NoiseWorm3D(pitch, yaw, size, start, (int)(wormStartNoise->getNoise(start.x, start.y, start.z) * (maxDistant - minDistant) + minDistant), minRadius, maxRadius);
  117. if (cache.getEintragAnzahl() > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  118. cache.remove(0);
  119. cache.add(worm);
  120. return worm;
  121. }
  122. else
  123. {
  124. if (noWormChunks.getEintragAnzahl() > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  125. noWormChunks.remove(0);
  126. noWormChunks.add(Punkt(x, y));
  127. }
  128. return 0;
  129. }
  130. void WormCaveGenerator::initialize(int seed)
  131. {
  132. wormStartNoise = new RandNoise(seed);
  133. }
  134. CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
  135. {
  136. Framework::RCArray<NoiseWorm3D> affected;
  137. Punkt center = Game::getChunkCenter(x, y);
  138. int offset = (int)ceil((float)maxDistant / CHUNK_SIZE);
  139. for (int cx = -offset; cx <= offset; cx++)
  140. {
  141. for (int cy = -offset; cy <= offset; cy++)
  142. {
  143. NoiseWorm3D* worm = zWormOfChunk(center.x + cx * CHUNK_SIZE, center.y + cy * CHUNK_SIZE);
  144. if (worm && worm->isChunkAffected(x, y))
  145. affected.add(dynamic_cast<NoiseWorm3D*>(worm->getThis()));
  146. }
  147. }
  148. return new WormCaveChunkGenerator(affected);
  149. }