WormCaveGenerator.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "WormCaveGenerator.h"
  2. #include "FastNoiseWrapper.h"
  3. #include "Game.h"
  4. #include "RandNoise.h"
  5. NoiseWorm3D::NoiseWorm3D()
  6. : ReferenceCounter()
  7. {}
  8. NoiseWorm3D::NoiseWorm3D(Noise* pitch,
  9. Noise* yaw,
  10. Noise* size,
  11. Framework::Vec3<int> startPos,
  12. int distant,
  13. int minRad,
  14. int maxRad)
  15. : ReferenceCounter(),
  16. startChunk(Game::INSTANCE->getChunkCenter(startPos.x, startPos.y))
  17. {
  18. Vec3<float> lastPos = (Vec3<float>)startPos;
  19. keyPoints.add(lastPos);
  20. this->size.add((float)minRad);
  21. minAffected.x = (int)lastPos.x - minRad;
  22. minAffected.y = (int)lastPos.y - minRad;
  23. maxAffected.x = (int)lastPos.x + minRad;
  24. maxAffected.y = (int)lastPos.y + minRad;
  25. while (keyPoints.getEintragAnzahl() < distant * 20)
  26. {
  27. Vec3<float> defaultDir(1.f, 0.f, 0.f);
  28. if (keyPoints.getEintragAnzahl() > 1)
  29. {
  30. defaultDir = keyPoints.get(keyPoints.getEintragAnzahl() - 1)
  31. - keyPoints.get(keyPoints.getEintragAnzahl() - 2);
  32. }
  33. float n = (float)yaw->getNoise(lastPos.x, lastPos.y, lastPos.z);
  34. defaultDir.rotateZ((n - 0.5f) / 2.f);
  35. defaultDir.normalize();
  36. n = (float)pitch->getNoise(lastPos.x, lastPos.y, lastPos.z);
  37. defaultDir.z = ((float)n - 0.3f) * 2.f;
  38. lastPos = lastPos + defaultDir;
  39. if ((Vec2<float>(lastPos.x, lastPos.y)
  40. - (Vec2<float>((float)startPos.x, (float)startPos.y)))
  41. .getLengthSq()
  42. >= (float)(distant * distant))
  43. break;
  44. keyPoints.add(lastPos);
  45. float rad = (float)size->getNoise(lastPos.x, lastPos.y, lastPos.z)
  46. * (float)(maxRad - minRad)
  47. + (float)minRad;
  48. this->size.add(rad);
  49. minAffected.x = MIN(minAffected.x, (int)(lastPos.x - rad));
  50. minAffected.y = MIN(minAffected.y, (int)(lastPos.y - rad));
  51. maxAffected.x = MAX(maxAffected.x, (int)(lastPos.x + rad));
  52. maxAffected.y = MAX(maxAffected.y, (int)(lastPos.y + rad));
  53. }
  54. }
  55. Framework::Punkt NoiseWorm3D::getStartChunkCenter()
  56. {
  57. return startChunk;
  58. }
  59. NoiseWorm3D *NoiseWorm3D::getPartAffectedByChunk(int x, int y)
  60. {
  61. NoiseWorm3D* result = 0;
  62. if (x - CHUNK_SIZE / 2 <= maxAffected.x
  63. && x + CHUNK_SIZE / 2 >= minAffected.x
  64. && y - CHUNK_SIZE / 2 <= maxAffected.y
  65. && y + CHUNK_SIZE / 2 >= minAffected.y)
  66. {
  67. auto pi = keyPoints.begin();
  68. auto si = size.begin();
  69. while (pi && si)
  70. {
  71. if ((Vec2<float>((float)x, (float)y)
  72. - Vec2<float>(pi.val().x, pi.val().y))
  73. .getLengthSq()
  74. < (si.val() + CHUNK_SIZE / 2) * (si.val() + CHUNK_SIZE / 2))
  75. {
  76. if (result == 0)
  77. {
  78. result = new NoiseWorm3D();
  79. }
  80. result->keyPoints.add(pi.val());
  81. result->size.add(si.val());
  82. }
  83. ++pi;
  84. ++si;
  85. }
  86. }
  87. return result;
  88. }
  89. bool NoiseWorm3D::isInside(int x, int y, int z)
  90. {
  91. auto pi = keyPoints.begin();
  92. auto si = size.begin();
  93. while (pi && si)
  94. {
  95. if (Vec3<float>((float)x, (float)y, (float)z).abstandSq(pi.val())
  96. < si.val() * si.val())
  97. return 1;
  98. ++pi;
  99. ++si;
  100. }
  101. return 0;
  102. }
  103. WormCaveChunkGenerator::WormCaveChunkGenerator(
  104. Framework::RCArray<NoiseWorm3D> worms)
  105. : CaveChunkGenerator(),
  106. worms(worms)
  107. {}
  108. bool WormCaveChunkGenerator::isInCave(int x, int y, int z)
  109. {
  110. for (NoiseWorm3D* w : worms)
  111. {
  112. if (w->isInside(x, y, z)) return 1;
  113. }
  114. return 0;
  115. }
  116. WormCaveGenerator::WormCaveGenerator(int minDistant,
  117. int maxDistant,
  118. int minRadius,
  119. int maxRadius,
  120. float cavePosibillityPerChunk)
  121. : CaveGenerator(),
  122. maxDistant(maxDistant),
  123. minDistant(minDistant),
  124. maxRadius(maxRadius),
  125. minRadius(minRadius),
  126. cavePosibillity(cavePosibillityPerChunk)
  127. {}
  128. WormCaveGenerator::~WormCaveGenerator()
  129. {
  130. wormStartNoise->release();
  131. }
  132. NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
  133. {
  134. for (NoiseWorm3D* worm : cache)
  135. {
  136. if (worm->getStartChunkCenter().x == x
  137. && worm->getStartChunkCenter().y == y)
  138. {
  139. return worm;
  140. }
  141. }
  142. for (Punkt p : noWormChunks)
  143. {
  144. if (p.x == x && p.y == y) return 0;
  145. }
  146. float cNoise = (float)wormStartNoise->getNoise(x, y, 0);
  147. if (cNoise < cavePosibillity)
  148. {
  149. FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
  150. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  151. noise->SetFrequency(0.05f);
  152. FastNoiseWrapper* pitch
  153. = new FastNoiseWrapper(noise, seed + x * y + y + x);
  154. noise = new FastNoiseLite(seed + x * y + y + x);
  155. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  156. noise->SetFrequency(0.005f);
  157. FastNoiseWrapper* yaw
  158. = new FastNoiseWrapper(noise, seed - x * y - y - x);
  159. Vec3<int> start(
  160. (int)(cNoise / cavePosibillity * CHUNK_SIZE) + x - CHUNK_SIZE / 2,
  161. (int)(cNoise / cavePosibillity * CHUNK_SIZE) + y - CHUNK_SIZE / 2,
  162. (int)(cNoise / cavePosibillity * 200));
  163. noise = new FastNoiseLite(
  164. seed + start.getLengthSq() + start.x + start.y + start.z);
  165. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  166. noise->SetFrequency(0.005f);
  167. FastNoiseWrapper* size = new FastNoiseWrapper(
  168. noise, seed + start.getLengthSq() + start.x + start.y + start.z);
  169. NoiseWorm3D* worm = new NoiseWorm3D(pitch,
  170. yaw,
  171. size,
  172. start,
  173. (int)(wormStartNoise->getNoise(start.x, start.y, start.z)
  174. * (maxDistant - minDistant)
  175. + minDistant),
  176. minRadius,
  177. maxRadius);
  178. if (cache.getEintragAnzahl()
  179. > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  180. cache.remove(0);
  181. cache.add(worm);
  182. return worm;
  183. }
  184. else
  185. {
  186. if (noWormChunks.getEintragAnzahl()
  187. > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  188. noWormChunks.remove(0);
  189. noWormChunks.add(Punkt(x, y));
  190. }
  191. return 0;
  192. }
  193. void WormCaveGenerator::initialize(int seed)
  194. {
  195. wormStartNoise = new RandNoise(seed);
  196. CaveGenerator::initialize(seed);
  197. }
  198. CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
  199. {
  200. Framework::RCArray<NoiseWorm3D> affected;
  201. Punkt center = Game::getChunkCenter(x, y);
  202. int offset = (int)ceil((float)maxDistant / CHUNK_SIZE);
  203. for (int cx = -offset; cx <= offset; cx++)
  204. {
  205. for (int cy = -offset; cy <= offset; cy++)
  206. {
  207. NoiseWorm3D* worm = zWormOfChunk(
  208. center.x + cx * CHUNK_SIZE, center.y + cy * CHUNK_SIZE);
  209. if (worm)
  210. {
  211. NoiseWorm3D* cuttedWorm = worm->getPartAffectedByChunk(x, y);
  212. if (cuttedWorm) affected.add(cuttedWorm);
  213. }
  214. }
  215. }
  216. return new WormCaveChunkGenerator(affected);
  217. }