Browse Source

add some basic caves

Kolja Strohm 2 years ago
parent
commit
677429fe6f

+ 1 - 0
FactoryCraft/BiomGenerator.h

@@ -20,6 +20,7 @@ public:
 	BiomGenerator();
 	virtual Framework::Either<Block*, int> generateSurfaceBlock(int x, int y, int z) = 0;
 	virtual Framework::Either<Block*, int> generateBelowSurfaceBlock(int x, int y, int z) = 0;
+	virtual Framework::Either<Block*, int> generateCaveBlock(int x, int y, int z) = 0;
 	virtual Noise* zHeightMapNoise(int seed) = 0;
 	const Framework::RCArray<GenerationTemplate>& getTemplates();
 };

+ 18 - 0
FactoryCraft/CaveGenerator.cpp

@@ -0,0 +1,18 @@
+#include "CaveGenerator.h"
+
+using namespace Framework;
+
+
+CaveChunkGenerator::CaveChunkGenerator()
+	: ReferenceCounter()
+{}
+
+
+CaveGenerator::CaveGenerator()
+	: ReferenceCounter()
+{}
+
+void CaveGenerator::initialize(int seed)
+{
+	this->seed = seed;
+}

+ 21 - 0
FactoryCraft/CaveGenerator.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include <ReferenceCounter.h>
+
+class CaveChunkGenerator : public virtual Framework::ReferenceCounter
+{
+public:
+	CaveChunkGenerator();
+	virtual bool isInCave(int x, int y, int z) = 0;
+};
+
+class CaveGenerator : public virtual Framework::ReferenceCounter
+{
+protected:
+	int seed;
+
+public:
+	CaveGenerator();
+	virtual void initialize(int seed);
+	virtual CaveChunkGenerator* getGeneratorForChunk(int x, int y) = 0;
+};

+ 30 - 19
FactoryCraft/DimensionGenerator.cpp

@@ -6,11 +6,12 @@
 #include <iostream>
 
 
-DimensionGenerator::DimensionGenerator(int dimensionId)
+DimensionGenerator::DimensionGenerator(int dimensionId, CaveGenerator* caveGenerator)
 	: ReferenceCounter(),
 	dimensionId(dimensionId),
 	minTemplateAffectedPosition(0, 0, 0),
-	maxTemplateAffectedPosition(0, 0, 0)
+	maxTemplateAffectedPosition(0, 0, 0),
+	caveGenerator(caveGenerator)
 {
 	StaticRegistry<DimensionGenerator>::INSTANCE.registerT(this, dimensionId);
 }
@@ -18,9 +19,15 @@ DimensionGenerator::DimensionGenerator(int dimensionId)
 DimensionGenerator::~DimensionGenerator()
 {}
 
-BiomGenerator* DimensionGenerator::zBiomGenerator(int seed, int x, int y)
+void DimensionGenerator::initialize(int seed)
 {
-	double noise = zBiomNoise(seed)->getNoise((double)x, (double)y, 0.0);
+	this->seed = seed + dimensionId;
+	caveGenerator->initialize(this->seed);
+}
+
+BiomGenerator* DimensionGenerator::zBiomGenerator(int x, int y)
+{
+	double noise = zBiomNoise()->getNoise((double)x, (double)y, 0.0);
 	double border = 0;
 	BiomGenerator* gen = 0;
 	auto genI = biomGenerators.begin();
@@ -48,7 +55,7 @@ void DimensionGenerator::registerBiom(BiomGenerator* generator, double possibili
 	}
 }
 
-Framework::RCArray<GeneratedStructure>* DimensionGenerator::getGeneratedStructoresForArea(int seed, Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos)
+Framework::RCArray<GeneratedStructure>* DimensionGenerator::getGeneratedStructoresForArea(Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos)
 {
 	Framework::RCArray<GeneratedStructure>* result = new Framework::RCArray<GeneratedStructure>();
 
@@ -59,13 +66,13 @@ Framework::RCArray<GeneratedStructure>* DimensionGenerator::getGeneratedStructor
 	int maxSearchY = maxPos.y - minTemplateAffectedPosition.y;
 	int maxSearchZ = MIN(maxPos.z - minTemplateAffectedPosition.z, WORLD_HEIGHT - 1);
 
-	Noise* structureNoise = zStructureNoise(seed + dimensionId);
+	Noise* structureNoise = zStructureNoise();
 	for (int x = minSearchX; x <= maxSearchX; x++)
 	{
 		for (int y = minSearchY; y <= maxSearchY; y++)
 		{
-			BiomGenerator* biom = zBiomGenerator(seed + dimensionId, x, y);
-			int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise(seed + dimensionId)->getNoise((double)(x), (double)(y), 0.0) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
+			BiomGenerator* biom = zBiomGenerator(x, y);
+			int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise(seed)->getNoise((double)(x), (double)(y), 0.0) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
 			for (int z = minSearchZ; z <= maxSearchZ; z++)
 			{
 				if (z < height)
@@ -92,20 +99,21 @@ Framework::RCArray<GeneratedStructure>* DimensionGenerator::getGeneratedStructor
 	return result;
 }
 
-Chunk* DimensionGenerator::generateChunk(int seed, int centerX, int centerY)
+Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
 {
-	Framework::RCArray<GeneratedStructure>* structures = getGeneratedStructoresForArea(seed, Framework::Vec3<int>(centerX - CHUNK_SIZE / 2, centerY - CHUNK_SIZE / 2, 0), Framework::Vec3<int>(centerX + CHUNK_SIZE / 2, centerY + CHUNK_SIZE / 2, WORLD_HEIGHT - 1));
+	Framework::RCArray<GeneratedStructure>* structures = getGeneratedStructoresForArea(Framework::Vec3<int>(centerX - CHUNK_SIZE / 2, centerY - CHUNK_SIZE / 2, 0), Framework::Vec3<int>(centerX + CHUNK_SIZE / 2, centerY + CHUNK_SIZE / 2, WORLD_HEIGHT - 1));
 	std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
+	CaveChunkGenerator* caveGen = caveGenerator->getGeneratorForChunk(centerX, centerY);
 	Chunk* chunk = new Chunk(Framework::Punkt(centerX, centerY), dimensionId);
 	for (int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++)
 	{
 		for (int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++)
 		{
-			BiomGenerator* biom = zBiomGenerator(seed + dimensionId, x + centerX, y + centerY);
+			BiomGenerator* biom = zBiomGenerator(x + centerX, y + centerY);
 			// TODO: use Noise interpolator for height map between different bioms
-			int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise(seed + dimensionId)->getNoise((double)(x + centerX), (double)(y + centerY), 0.0) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
+			int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise(seed)->getNoise((double)(x + centerX), (double)(y + centerY), 0.0) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
 			int maxSurfaceHeight = (int)(MAX_SURFACE_HEIGHT * (1.f - (float)(height - MIN_AIR_LEVEL) / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
-			int actualSurfaceHeight = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART) + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART * (float)biom->zHeightMapNoise(seed + dimensionId)->getNoise((double)(x + centerX), (double)(y + centerY), 10.0)));
+			int actualSurfaceHeight = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART) + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART * (float)biom->zHeightMapNoise(seed)->getNoise((double)(x + centerX), (double)(y + centerY), 10.0)));
 			for (int z = 0; z < WORLD_HEIGHT; z++)
 			{
 				Framework::Either<Block*, int> generated = AirBlockBlockType::ID;
@@ -121,7 +129,9 @@ Chunk* DimensionGenerator::generateChunk(int seed, int centerX, int centerY)
 				}
 				if (!structureAffected)
 				{
-					if (z < height && z >= height - actualSurfaceHeight)
+					if (caveGen->isInCave(x + centerX, y + centerY, z))
+						generated = biom->generateCaveBlock(x + centerX, y + centerY, z);
+					else if (z < height && z >= height - actualSurfaceHeight)
 						generated = biom->generateSurfaceBlock(x + centerX, y + centerY, z);
 					else if (z < height)
 						generated = biom->generateBelowSurfaceBlock(x + centerX, y + centerY, z);
@@ -133,18 +143,19 @@ Chunk* DimensionGenerator::generateChunk(int seed, int centerX, int centerY)
 			}
 		}
 	}
+	caveGen->release();
 	structures->release();
 	return chunk;
 }
 
-Framework::Either<Block*, int> DimensionGenerator::generateBlock(int seed, Framework::Vec3<int> location)
+Framework::Either<Block*, int> DimensionGenerator::generateBlock(Framework::Vec3<int> location)
 {
-	Framework::RCArray<GeneratedStructure>* structures = getGeneratedStructoresForArea(seed, location, location);
-	BiomGenerator* biom = zBiomGenerator(seed + dimensionId, location.x, location.y);
+	Framework::RCArray<GeneratedStructure>* structures = getGeneratedStructoresForArea(location, location);
+	BiomGenerator* biom = zBiomGenerator(location.x, location.y);
 	// TODO: use Noise interpolator for height map between different bioms
-	int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise(seed + dimensionId)->getNoise((double)(location.x), (double)(location.y), 0.0) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
+	int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise(seed)->getNoise((double)(location.x), (double)(location.y), 0.0) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
 	int maxSurfaceHeight = (int)(MAX_SURFACE_HEIGHT * (1.f - (float)(height - MIN_AIR_LEVEL) / (float)(MAX_AIR_LEVEL - MIN_AIR_LEVEL)));
-	int actualSurfaceHeight = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART) + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART * (float)biom->zHeightMapNoise(seed + dimensionId)->getNoise((double)(location.x), (double)(location.y), 10.0)));
+	int actualSurfaceHeight = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART) + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART * (float)biom->zHeightMapNoise(seed)->getNoise((double)(location.x), (double)(location.y), 10.0)));
 	for (auto structure : *structures)
 	{
 		if (structure->isBlockAffected(location))

+ 11 - 7
FactoryCraft/DimensionGenerator.h

@@ -6,6 +6,7 @@
 
 #include "BiomGenerator.h"
 #include "Chunk.h"
+#include "CaveGenerator.h"
 
 class DimensionGenerator : public virtual Framework::ReferenceCounter
 {
@@ -15,19 +16,22 @@ private:
 	const int dimensionId;
 	Framework::Vec3<int> minTemplateAffectedPosition;
 	Framework::Vec3<int> maxTemplateAffectedPosition;
+	CaveGenerator* caveGenerator;
 
-	BiomGenerator* zBiomGenerator(int seed, int x, int y);
+	BiomGenerator* zBiomGenerator(int x, int y);
 
 protected:
-	DimensionGenerator(int dimensionId);
+	int seed;
+	DimensionGenerator(int dimensionId, CaveGenerator* caveGenerator);
 	~DimensionGenerator();
 	void registerBiom(BiomGenerator* generator, double possibility);
-	Framework::RCArray<GeneratedStructure>* getGeneratedStructoresForArea(int seed, Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos);
+	Framework::RCArray<GeneratedStructure>* getGeneratedStructoresForArea(Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos);
 
 public:
-	Chunk* generateChunk(int seed, int centerX, int centerY);
-	Framework::Either<Block*, int> generateBlock(int seed, Framework::Vec3<int> location);
+	void initialize(int seed);
+	Chunk* generateChunk(int centerX, int centerY);
+	Framework::Either<Block*, int> generateBlock(Framework::Vec3<int> location);
 	int getDimensionId() const;
-	virtual Noise* zBiomNoise(int seed) = 0;
-	virtual Noise* zStructureNoise(int seed) = 0;
+	virtual Noise* zBiomNoise() = 0;
+	virtual Noise* zStructureNoise() = 0;
 };

+ 4 - 0
FactoryCraft/FactoryCraft.vcxproj

@@ -99,6 +99,7 @@
     <ClInclude Include="BiomGenerator.h" />
     <ClInclude Include="Block.h" />
     <ClInclude Include="BlockType.h" />
+    <ClInclude Include="CaveGenerator.h" />
     <ClInclude Include="Chunk.h" />
     <ClInclude Include="Constants.h" />
     <ClInclude Include="CraftingStorage.h" />
@@ -147,6 +148,7 @@
     <ClInclude Include="WorldGenerator.h" />
     <ClInclude Include="WorldLoader.h" />
     <ClInclude Include="WorldUpdate.h" />
+    <ClInclude Include="WormCaveGenerator.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="AddEntityUpdate.cpp" />
@@ -156,6 +158,7 @@
     <ClCompile Include="BiomGenerator.cpp" />
     <ClCompile Include="Block.cpp" />
     <ClCompile Include="BlockType.cpp" />
+    <ClCompile Include="CaveGenerator.cpp" />
     <ClCompile Include="Chunk.cpp" />
     <ClCompile Include="CraftingStorage.cpp" />
     <ClCompile Include="Dimension.cpp" />
@@ -200,6 +203,7 @@
     <ClCompile Include="WorldGenerator.cpp" />
     <ClCompile Include="WorldLoader.cpp" />
     <ClCompile Include="WorldUpdate.cpp" />
+    <ClCompile Include="WormCaveGenerator.cpp" />
   </ItemGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <Link>

+ 15 - 0
FactoryCraft/FactoryCraft.vcxproj.filters

@@ -61,6 +61,9 @@
     <Filter Include="inventory\recipies">
       <UniqueIdentifier>{3289186e-1fb6-40a2-afb6-f9c87adaec62}</UniqueIdentifier>
     </Filter>
+    <Filter Include="world\generator\caves">
+      <UniqueIdentifier>{0a074c6e-f64a-4854-9f25-a8e933272e29}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Chunk.h">
@@ -228,6 +231,12 @@
     <ClInclude Include="LightSources.h">
       <Filter>world\blocks</Filter>
     </ClInclude>
+    <ClInclude Include="CaveGenerator.h">
+      <Filter>world\generator\caves</Filter>
+    </ClInclude>
+    <ClInclude Include="WormCaveGenerator.h">
+      <Filter>world\generator\caves</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Server.cpp">
@@ -383,5 +392,11 @@
     <ClCompile Include="LightSources.cpp">
       <Filter>world\blocks</Filter>
     </ClCompile>
+    <ClCompile Include="WormCaveGenerator.cpp">
+      <Filter>world\generator\caves</Filter>
+    </ClCompile>
+    <ClCompile Include="CaveGenerator.cpp">
+      <Filter>world\generator\caves</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 1
FactoryCraft/Game.cpp

@@ -57,7 +57,7 @@ GameClient::~GameClient()
 	emptyBackgroundQueueSync.notifyAll();
 	foregroundQueueSync.notify();
 	backgroundQueueSync.notify();
-	while (!finished ||!backgroundFinished || !backgroundFinished)
+	while (!finished || !foregroundFinished || !backgroundFinished)
 		Sleep(100);
 	client->release();
 }

+ 6 - 0
FactoryCraft/GrasslandBiom.cpp

@@ -4,6 +4,7 @@
 #include "FastNoiseLite.h"
 #include "FastNoiseWrapper.h"
 #include "TreeTemplate.h"
+#include "NoBlock.h"
 
 
 GrasslandBiom::GrasslandBiom()
@@ -34,6 +35,11 @@ Framework::Either<Block*, int> GrasslandBiom::generateBelowSurfaceBlock(int x, i
 	return StoneBlockType::ID;
 }
 
+Framework::Either<Block*, int> GrasslandBiom::generateCaveBlock(int x, int y, int z)
+{
+	return AirBlockBlockType::ID;
+}
+
 Noise* GrasslandBiom::zHeightMapNoise(int seed)
 {
 	if (heightNoise)

+ 1 - 0
FactoryCraft/GrasslandBiom.h

@@ -12,5 +12,6 @@ public:
 	~GrasslandBiom();
 	Framework::Either<Block*, int> generateSurfaceBlock(int x, int y, int z) override;
 	Framework::Either<Block*, int> generateBelowSurfaceBlock(int x, int y, int z) override;
+	Framework::Either<Block*, int> generateCaveBlock(int x, int y, int z) override;
 	Noise* zHeightMapNoise(int seed) override;
 };

+ 4 - 3
FactoryCraft/OverworldDimension.cpp

@@ -2,10 +2,11 @@
 #include "GrasslandBiom.h"
 #include "FastNoiseWrapper.h"
 #include "RandNoise.h"
+#include "WormCaveGenerator.h"
 
 
 OverworldDimension::OverworldDimension()
-	: DimensionGenerator(ID)
+	: DimensionGenerator(ID, new WormCaveGenerator(75, 150, 1, 6, 0.1f))
 {
 	registerBiom(new GrasslandBiom(), 1.0);
 	biomNoise = 0;
@@ -20,7 +21,7 @@ OverworldDimension::~OverworldDimension()
 		structureNoise->release();
 }
 
-Noise* OverworldDimension::zBiomNoise(int seed)
+Noise* OverworldDimension::zBiomNoise()
 {
 	if (biomNoise)
 		return biomNoise;
@@ -38,7 +39,7 @@ Noise* OverworldDimension::zBiomNoise(int seed)
 	return biomNoise;
 }
 
-Noise* OverworldDimension::zStructureNoise(int seed)
+Noise* OverworldDimension::zStructureNoise()
 {
 	if (structureNoise)
 		return structureNoise;

+ 2 - 3
FactoryCraft/OverworldDimension.h

@@ -15,9 +15,8 @@ private:
 public:
 	OverworldDimension();
 	~OverworldDimension();
-
-	Noise* zBiomNoise(int seed) override;
-	Noise* zStructureNoise(int seed) override;
+	Noise* zBiomNoise() override;
+	Noise* zStructureNoise() override;
 };
 
 #ifdef REGISTER

+ 4 - 2
FactoryCraft/WorldGenerator.cpp

@@ -11,6 +11,8 @@ WorldGenerator::WorldGenerator(int seed)
 	seed(seed)
 {
 	setName("World Generator");
+	for (int i = 0; i < StaticRegistry<DimensionGenerator>::INSTANCE.getCount(); i++)
+		StaticRegistry<DimensionGenerator>::INSTANCE.zElement(i)->initialize(seed);
 	start();
 }
 
@@ -46,7 +48,7 @@ void WorldGenerator::thread()
 			{
 				if (!Game::INSTANCE->doesChunkExist(x, y, next.dimensionId))
 				{
-					Chunk* generatedChunk = StaticRegistry<DimensionGenerator>::INSTANCE.zElement(next.dimensionId)->generateChunk(seed, x, y);
+					Chunk* generatedChunk = StaticRegistry<DimensionGenerator>::INSTANCE.zElement(next.dimensionId)->generateChunk(x, y);
 					generatedChunk->initializeLightning();
 					generatedChunk->removeUnusedBlocks();
 					Dimension* dim = Game::INSTANCE->zDimension(next.dimensionId);
@@ -78,5 +80,5 @@ void WorldGenerator::exitAndWait()
 
 Framework::Either<Block*, int> WorldGenerator::generateSingleBlock(Framework::Vec3<int> location, int dimensionId)
 {
-	return StaticRegistry<DimensionGenerator>::INSTANCE.zElement(dimensionId)->generateBlock(seed, location);
+	return StaticRegistry<DimensionGenerator>::INSTANCE.zElement(dimensionId)->generateBlock(location);
 }

+ 163 - 0
FactoryCraft/WormCaveGenerator.cpp

@@ -0,0 +1,163 @@
+#include "WormCaveGenerator.h"
+#include "Game.h"
+#include "FastNoiseWrapper.h"
+#include "RandNoise.h"
+
+
+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))
+{
+	Vec3<float> lastPos = (Vec3<float>)startPos;
+	keyPoints.add(lastPos);
+	this->size.add((float)minRad);
+	minAffected.x = (int)lastPos.x - minRad;
+	minAffected.y = (int)lastPos.y - minRad;
+	maxAffected.x = (int)lastPos.x + minRad;
+	maxAffected.y = (int)lastPos.y + minRad;
+	while (keyPoints.getEintragAnzahl() < distant * 20)
+	{
+		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.5) / 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 ((Vec2<float>(lastPos.x, lastPos.y) - (Vec2<float>((float)startPos.x, (float)startPos.y))).getLengthSq() >= 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));
+		maxAffected.x = MAX(maxAffected.x, (int)(lastPos.x + rad));
+		maxAffected.y = MAX(maxAffected.y, (int)(lastPos.y + rad));
+	}
+}
+
+Framework::Punkt NoiseWorm3D::getStartChunkCenter()
+{
+	return startChunk;
+}
+
+bool NoiseWorm3D::isChunkAffected(int x, int y)
+{
+	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;
+}
+
+bool NoiseWorm3D::isInside(int x, int y, int z)
+{
+	auto pi = keyPoints.begin();
+	auto si = size.begin();
+	while (pi && si)
+	{
+		if (Vec3<float>((float)x, (float)y, (float)z).abstand(pi.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)
+	: CaveGenerator(),
+	maxDistant(maxDistant),
+	minDistant(minDistant),
+	maxRadius(maxRadius),
+	minRadius(minRadius),
+	cavePosibillity(cavePosibillityPerChunk)
+{}
+
+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 (Punkt p : noWormChunks)
+	{
+		if (p.x == x && p.y == y)
+			return 0;
+	}
+	float cNoise = 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);
+		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 + x * y - y + x);
+		noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
+		noise->SetFrequency(0.05f);
+		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(Punkt(x, y));
+	}
+	return 0;
+}
+
+void WormCaveGenerator::initialize(int seed)
+{
+	wormStartNoise = new RandNoise(seed);
+}
+
+CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
+{
+	Framework::RCArray<NoiseWorm3D> affected;
+	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->isChunkAffected(x, y))
+				affected.add(dynamic_cast<NoiseWorm3D*>(worm->getThis()));
+		}
+	}
+	return new WormCaveChunkGenerator(affected);
+}

+ 59 - 0
FactoryCraft/WormCaveGenerator.h

@@ -0,0 +1,59 @@
+#pragma once
+
+#include <Vec3.h>
+#include <Array.h>
+#include <Punkt.h>
+
+#include "CaveGenerator.h"
+#include "Noise.h"
+
+class NoiseWorm3D : public Framework::ReferenceCounter
+{
+private:
+	Framework::Punkt startChunk;
+	Framework::Punkt minAffected;
+	Framework::Punkt maxAffected;
+
+	Framework::Array<Framework::Vec3<float>> keyPoints;
+	Framework::Array<float> size;
+
+public:
+	NoiseWorm3D(Noise* pitch, Noise* yaw, Noise* size, Framework::Vec3<int> startPos, int distant, int minRad, int maxRad);
+	Framework::Punkt getStartChunkCenter();
+	bool isChunkAffected(int x, int y);
+	bool isInside(int x, int y, int z);
+};
+
+
+class WormCaveChunkGenerator : public CaveChunkGenerator
+{
+private:
+	Framework::RCArray<NoiseWorm3D> worms;
+
+public:
+	WormCaveChunkGenerator(Framework::RCArray<NoiseWorm3D> worms);
+	bool isInCave(int x, int y, int z) override;
+};
+
+
+class WormCaveGenerator : public CaveGenerator
+{
+private:
+	int maxDistant;
+	int minDistant;
+	int maxRadius;
+	int minRadius;
+	float cavePosibillity;
+	Noise* wormStartNoise;
+	Framework::RCArray<NoiseWorm3D> cache;
+	Framework::Array<Framework::Punkt > noWormChunks;
+
+	NoiseWorm3D* zWormOfChunk(int x, int y);
+
+public:
+	WormCaveGenerator(int minDistant, int maxDistant, int minRadius, int maxRadius, float cavePosibillityPerChunk);
+	~WormCaveGenerator();
+	void initialize(int seed) override;
+
+	CaveChunkGenerator* getGeneratorForChunk(int x, int y) override;
+};