WormCaveGenerator.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. int seed)
  122. : CaveGenerator(seed),
  123. maxDistant(maxDistant),
  124. minDistant(minDistant),
  125. maxRadius(maxRadius),
  126. minRadius(minRadius),
  127. cavePosibillity(cavePosibillityPerChunk),
  128. wormStartNoise(new RandNoise(seed))
  129. {}
  130. WormCaveGenerator::~WormCaveGenerator()
  131. {
  132. wormStartNoise->release();
  133. }
  134. NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
  135. {
  136. for (NoiseWorm3D* worm : cache)
  137. {
  138. if (worm->getStartChunkCenter().x == x
  139. && worm->getStartChunkCenter().y == y)
  140. {
  141. return worm;
  142. }
  143. }
  144. for (Punkt p : noWormChunks)
  145. {
  146. if (p.x == x && p.y == y) return 0;
  147. }
  148. float cNoise = (float)wormStartNoise->getNoise(x, y, 0);
  149. if (cNoise < cavePosibillity)
  150. {
  151. FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
  152. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  153. noise->SetFrequency(0.05f);
  154. FastNoiseWrapper* pitch
  155. = new FastNoiseWrapper(noise, seed + x * y + y + x);
  156. noise = new FastNoiseLite(seed + x * y + y + x);
  157. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  158. noise->SetFrequency(0.005f);
  159. FastNoiseWrapper* yaw
  160. = new FastNoiseWrapper(noise, seed - x * y - y - x);
  161. Vec3<int> start(
  162. (int)(cNoise / cavePosibillity * CHUNK_SIZE) + x - CHUNK_SIZE / 2,
  163. (int)(cNoise / cavePosibillity * CHUNK_SIZE) + y - CHUNK_SIZE / 2,
  164. (int)(cNoise / cavePosibillity * 200));
  165. noise = new FastNoiseLite(
  166. seed + start.getLengthSq() + start.x + start.y + start.z);
  167. noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
  168. noise->SetFrequency(0.005f);
  169. FastNoiseWrapper* size = new FastNoiseWrapper(
  170. noise, seed + start.getLengthSq() + start.x + start.y + start.z);
  171. NoiseWorm3D* worm = new NoiseWorm3D(pitch,
  172. yaw,
  173. size,
  174. start,
  175. (int)(wormStartNoise->getNoise(start.x, start.y, start.z)
  176. * (maxDistant - minDistant)
  177. + minDistant),
  178. minRadius,
  179. maxRadius);
  180. if (cache.getEintragAnzahl()
  181. > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  182. cache.remove(0);
  183. cache.add(worm);
  184. return worm;
  185. }
  186. else
  187. {
  188. if (noWormChunks.getEintragAnzahl()
  189. > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
  190. noWormChunks.remove(0);
  191. noWormChunks.add(Punkt(x, y));
  192. }
  193. return 0;
  194. }
  195. CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
  196. {
  197. Framework::RCArray<NoiseWorm3D> affected;
  198. Punkt center = Game::getChunkCenter(x, y);
  199. int offset = (int)ceil((float)maxDistant / CHUNK_SIZE);
  200. for (int cx = -offset; cx <= offset; cx++)
  201. {
  202. for (int cy = -offset; cy <= offset; cy++)
  203. {
  204. NoiseWorm3D* worm = zWormOfChunk(
  205. center.x + cx * CHUNK_SIZE, center.y + cy * CHUNK_SIZE);
  206. if (worm)
  207. {
  208. NoiseWorm3D* cuttedWorm = worm->getPartAffectedByChunk(x, y);
  209. if (cuttedWorm) affected.add(cuttedWorm);
  210. }
  211. }
  212. }
  213. return new WormCaveChunkGenerator(affected);
  214. }