123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #include "WormCaveGenerator.h"
- #include "Constants.h"
- #include "FastNoiseWrapper.h"
- #include "Game.h"
- #include "RandNoise.h"
- NoiseWorm3D::NoiseWorm3D()
- : ReferenceCounter()
- {}
- NoiseWorm3D::NoiseWorm3D(Noise* pitch,
- Noise* yaw,
- Noise* size,
- Framework::Vec3<int> startPos,
- int distant,
- int minRad,
- int maxRad)
- : ReferenceCounter(),
- startChunk(Game::INSTANCE->getChunkCenter(startPos.x, startPos.y))
- {
- Framework::Vec3<float> lastPos = (Framework::Vec3<float>)startPos;
- keyPoints.add(lastPos);
- this->size.add((float)minRad);
- minAffected.x = (int)lastPos.x - minRad;
- minAffected.y = (int)lastPos.y - minRad;
- minAffected.z = (int)lastPos.z - minRad;
- maxAffected.x = (int)lastPos.x + minRad;
- maxAffected.y = (int)lastPos.y + minRad;
- maxAffected.z = (int)lastPos.z + minRad;
- while (keyPoints.getEintragAnzahl() < distant * 20)
- {
- Framework::Vec3<float> defaultDir(1.f, 0.f, 0.f);
- if (keyPoints.getEintragAnzahl() > 1)
- {
- defaultDir = keyPoints.get(keyPoints.getEintragAnzahl() - 1)
- - keyPoints.get(keyPoints.getEintragAnzahl() - 2);
- }
- float n = (float)yaw->getNoise(lastPos.x, lastPos.y, lastPos.z);
- defaultDir.rotateZ((n - 0.5f) / 2.f);
- defaultDir.normalize();
- n = (float)pitch->getNoise(lastPos.x, lastPos.y, lastPos.z);
- defaultDir.z = ((float)n - 0.3f) * 2.f;
- lastPos = lastPos + defaultDir;
- if ((Framework::Vec2<float>(lastPos.x, lastPos.y)
- - (Framework::Vec2<float>(
- (float)startPos.x, (float)startPos.y)))
- .getLengthSq()
- >= (float)(distant * distant))
- break;
- keyPoints.add(lastPos);
- float rad = (float)size->getNoise(lastPos.x, lastPos.y, lastPos.z)
- * (float)(maxRad - minRad)
- + (float)minRad;
- this->size.add(rad);
- minAffected.x = MIN(minAffected.x, (int)(lastPos.x - rad));
- minAffected.y = MIN(minAffected.y, (int)(lastPos.y - rad));
- minAffected.z = MIN(minAffected.z, (int)(lastPos.z - rad));
- maxAffected.x = MAX(maxAffected.x, (int)(lastPos.x + rad));
- maxAffected.y = MAX(maxAffected.y, (int)(lastPos.y + rad));
- maxAffected.z = MAX(maxAffected.z, (int)(lastPos.z + rad));
- }
- }
- Framework::Punkt NoiseWorm3D::getStartChunkCenter()
- {
- return startChunk;
- }
- void NoiseWorm3D::getPartAffectedByChunk(
- int x, int y, Framework::RCArray<NoiseWorm3D>* zResult)
- {
- NoiseWorm3D* result = 0;
- 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)
- {
- auto pi = keyPoints.begin();
- auto si = size.begin();
- int newWormThreshold = 5;
- int outsideCounter = 0;
- while (pi && si)
- {
- if ((Framework::Vec2<float>((float)x, (float)y)
- - Framework::Vec2<float>(pi.val().x, pi.val().y))
- .getLengthSq()
- < (si.val() + CHUNK_SIZE / 2) * (si.val() + CHUNK_SIZE / 2))
- {
- outsideCounter = 0;
- if (result == 0)
- {
- result = new NoiseWorm3D();
- result->minAffected.x = (int)(pi.val().x - si.val());
- result->minAffected.y = (int)(pi.val().y - si.val());
- result->minAffected.z = (int)(pi.val().z - si.val());
- result->maxAffected.x = (int)(pi.val().x + si.val());
- result->maxAffected.y = (int)(pi.val().y + si.val());
- result->maxAffected.z = (int)(pi.val().z + si.val());
- }
- else
- {
- result->minAffected.x = MIN(
- result->minAffected.x, (int)(pi.val().x - si.val()));
- result->minAffected.y = MIN(
- result->minAffected.y, (int)(pi.val().y - si.val()));
- result->minAffected.z = MIN(
- result->minAffected.z, (int)(pi.val().z - si.val()));
- result->maxAffected.x = MAX(
- result->maxAffected.x, (int)(pi.val().x + si.val()));
- result->maxAffected.y = MAX(
- result->maxAffected.y, (int)(pi.val().y + si.val()));
- result->maxAffected.z = MAX(
- result->maxAffected.z, (int)(pi.val().z + si.val()));
- }
- result->keyPoints.add(pi.val());
- result->size.add(si.val());
- }
- else
- {
- outsideCounter++;
- if (outsideCounter >= newWormThreshold)
- {
- if (result != 0)
- {
- zResult->add(result);
- result = 0;
- }
- outsideCounter = 0;
- }
- }
- ++pi;
- ++si;
- }
- }
- if (result)
- {
- zResult->add(result);
- }
- }
- bool NoiseWorm3D::isInside(int x, int y, int z)
- {
- if (x >= minAffected.x && x <= maxAffected.x && y >= minAffected.y
- && y <= maxAffected.y && z >= minAffected.z && z <= maxAffected.z)
- {
- auto pi = keyPoints.begin();
- auto si = size.begin();
- while (pi && si)
- {
- if (Framework::Vec3<float>((float)x, (float)y, (float)z)
- .abstandSq(pi.val())
- < si.val() * si.val())
- return 1;
- ++pi;
- ++si;
- }
- }
- return 0;
- }
- WormCaveChunkGenerator::WormCaveChunkGenerator(
- Framework::RCArray<NoiseWorm3D> worms)
- : CaveChunkGenerator(),
- worms(worms)
- {}
- bool WormCaveChunkGenerator::isInCave(int x, int y, int z)
- {
- for (NoiseWorm3D* w : worms)
- {
- if (w->isInside(x, y, z)) return 1;
- }
- return 0;
- }
- WormCaveGenerator::WormCaveGenerator(int minDistant,
- int maxDistant,
- int minRadius,
- int maxRadius,
- float cavePosibillityPerChunk,
- int seed)
- : CaveGenerator(seed),
- maxDistant(maxDistant),
- minDistant(minDistant),
- maxRadius(maxRadius),
- minRadius(minRadius),
- cavePosibillity(cavePosibillityPerChunk),
- wormStartNoise(new RandNoise(seed))
- {}
- WormCaveGenerator::~WormCaveGenerator()
- {
- wormStartNoise->release();
- }
- NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
- {
- for (NoiseWorm3D* worm : cache)
- {
- if (worm->getStartChunkCenter().x == x
- && worm->getStartChunkCenter().y == y)
- {
- return worm;
- }
- }
- for (Framework::Punkt p : noWormChunks)
- {
- if (p.x == x && p.y == y) return 0;
- }
- float cNoise = (float)wormStartNoise->getNoise(x, y, 0);
- if (cNoise < cavePosibillity)
- {
- FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
- noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
- noise->SetFrequency(0.05f);
- FastNoiseWrapper* pitch
- = new FastNoiseWrapper(noise, seed + x * y + y + x);
- noise = new FastNoiseLite(seed + x * y + y + x);
- noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
- noise->SetFrequency(0.005f);
- FastNoiseWrapper* yaw
- = new FastNoiseWrapper(noise, seed - x * y - y - x);
- Framework::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));
- noise = new FastNoiseLite(
- seed + start.getLengthSq() + start.x + start.y + start.z);
- noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
- noise->SetFrequency(0.005f);
- FastNoiseWrapper* size = new FastNoiseWrapper(
- noise, seed + start.getLengthSq() + start.x + start.y + start.z);
- NoiseWorm3D* worm = new NoiseWorm3D(pitch,
- yaw,
- size,
- start,
- (int)(wormStartNoise->getNoise(start.x, start.y, start.z)
- * (maxDistant - minDistant)
- + minDistant),
- minRadius,
- maxRadius);
- if (cache.getEintragAnzahl()
- > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
- cache.remove(0);
- cache.add(worm);
- return worm;
- }
- else
- {
- if (noWormChunks.getEintragAnzahl()
- > (maxDistant * 2) / CHUNK_SIZE * (maxDistant * 2) / CHUNK_SIZE * 3)
- noWormChunks.remove(0);
- noWormChunks.add(Framework::Punkt(x, y));
- }
- return 0;
- }
- CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
- {
- Framework::RCArray<NoiseWorm3D> affected;
- Framework::Punkt center = Game::getChunkCenter(x, y);
- int offset = (int)ceil((float)maxDistant / CHUNK_SIZE);
- for (int cx = -offset; cx <= offset; cx++)
- {
- for (int cy = -offset; cy <= offset; cy++)
- {
- NoiseWorm3D* worm = zWormOfChunk(
- center.x + cx * CHUNK_SIZE, center.y + cy * CHUNK_SIZE);
- if (worm) worm->getPartAffectedByChunk(x, y, &affected);
- }
- }
- return new WormCaveChunkGenerator(affected);
- }
|