WormCaveGenerator.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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.5f) / 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() >= (float)(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. if (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. auto pi = keyPoints.begin();
  49. auto si = size.begin();
  50. while (pi && si)
  51. {
  52. if ((Vec2<float>((float)x, (float)y) - Vec2<float>(pi.val().x, pi.val().y)).getLengthSq() < (si.val() + CHUNK_SIZE / 2) * (si.val() + CHUNK_SIZE / 2))
  53. return 1;
  54. ++pi;
  55. ++si;
  56. }
  57. }
  58. return 0;
  59. }
  60. bool NoiseWorm3D::isInside(int x, int y, int z)
  61. {
  62. auto pi = keyPoints.begin();
  63. auto si = size.begin();
  64. while (pi && si)
  65. {
  66. if (Vec3<float>((float)x, (float)y, (float)z).abstand(pi.val()) < si.val())
  67. return 1;
  68. ++pi;
  69. ++si;
  70. }
  71. return 0;
  72. }
  73. WormCaveChunkGenerator::WormCaveChunkGenerator(Framework::RCArray<NoiseWorm3D> worms)
  74. : CaveChunkGenerator(),
  75. worms(worms)
  76. {}
  77. bool WormCaveChunkGenerator::isInCave(int x, int y, int z)
  78. {
  79. for (NoiseWorm3D* w : worms)
  80. {
  81. if (w->isInside(x, y, z))
  82. return 1;
  83. }
  84. return 0;
  85. }
  86. WormCaveGenerator::WormCaveGenerator(int minDistant, int maxDistant, int minRadius, int maxRadius, float cavePosibillityPerChunk)
  87. : CaveGenerator(),
  88. maxDistant(maxDistant),
  89. minDistant(minDistant),
  90. maxRadius(maxRadius),
  91. minRadius(minRadius),
  92. cavePosibillity(cavePosibillityPerChunk)
  93. {}
  94. WormCaveGenerator::~WormCaveGenerator()
  95. {
  96. wormStartNoise->release();
  97. }
  98. NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
  99. {
  100. for (NoiseWorm3D* worm : cache)
  101. {
  102. if (worm->getStartChunkCenter().x == x && worm->getStartChunkCenter().y == y)
  103. {
  104. return worm;
  105. }
  106. }
  107. for (Punkt p : noWormChunks)
  108. {
  109. if (p.x == x && p.y == y)
  110. return 0;
  111. }
  112. float cNoise = (float)wormStartNoise->getNoise(x, y, 0);
  113. if (cNoise < cavePosibillity)
  114. {
  115. FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
  116. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  117. noise->SetFrequency(0.05f);
  118. FastNoiseWrapper* pitch = new FastNoiseWrapper(noise, seed + x * y + y + x);
  119. noise = new FastNoiseLite(seed + x * y + y + x);
  120. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  121. noise->SetFrequency(0.005f);
  122. FastNoiseWrapper* yaw = new FastNoiseWrapper(noise, seed - x * y - y - x);
  123. 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));
  124. noise = new FastNoiseLite(seed + start.getLengthSq() + start.x + start.y + start.z);
  125. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  126. noise->SetFrequency(0.005f);
  127. FastNoiseWrapper* size = new FastNoiseWrapper(noise, seed + start.getLengthSq() + start.x + start.y + start.z);
  128. NoiseWorm3D* worm = new NoiseWorm3D(pitch, yaw, size, start, (int)(wormStartNoise->getNoise(start.x, start.y, start.z) * (maxDistant - minDistant) + minDistant), minRadius, maxRadius);
  129. if (cache.getEintragAnzahl() > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  130. cache.remove(0);
  131. cache.add(worm);
  132. return worm;
  133. }
  134. else
  135. {
  136. if (noWormChunks.getEintragAnzahl() > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  137. noWormChunks.remove(0);
  138. noWormChunks.add(Punkt(x, y));
  139. }
  140. return 0;
  141. }
  142. void WormCaveGenerator::initialize(int seed)
  143. {
  144. wormStartNoise = new RandNoise(seed);
  145. CaveGenerator::initialize(seed);
  146. }
  147. CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
  148. {
  149. Framework::RCArray<NoiseWorm3D> affected;
  150. Punkt center = Game::getChunkCenter(x, y);
  151. int offset = (int)ceil((float)maxDistant / CHUNK_SIZE);
  152. for (int cx = -offset; cx <= offset; cx++)
  153. {
  154. for (int cy = -offset; cy <= offset; cy++)
  155. {
  156. NoiseWorm3D* worm = zWormOfChunk(center.x + cx * CHUNK_SIZE, center.y + cy * CHUNK_SIZE);
  157. if (worm && worm->isChunkAffected(x, y))
  158. affected.add(dynamic_cast<NoiseWorm3D*>(worm->getThis()));
  159. }
  160. }
  161. return new WormCaveChunkGenerator(affected);
  162. }