Переглянути джерело

add sand, gravel and dirt deposits underground and improved the performance of cave generation

Kolja Strohm 1 рік тому
батько
коміт
e72d2995f3

+ 5 - 0
FactoryCraft/BiomGenerator.cpp

@@ -12,4 +12,9 @@ void BiomGenerator::addTemplateGenerator(GenerationTemplate* gTemplate)
 const Framework::RCArray<GenerationTemplate>& BiomGenerator::getTemplates()
 {
     return templates;
+}
+
+void BiomGenerator::setSeed(int seed)
+{
+    this->seed = seed;
 }

+ 3 - 1
FactoryCraft/BiomGenerator.h

@@ -14,6 +14,7 @@ private:
     Framework::RCArray<GenerationTemplate> templates;
 
 protected:
+    int seed;
     void addTemplateGenerator(GenerationTemplate* gTemplate);
 
 public:
@@ -27,6 +28,7 @@ public:
     virtual Framework::Either<Block*, int> generateCaveBlock(
         int x, int y, int z)
         = 0;
-    virtual Noise* zHeightMapNoise(int seed) = 0;
+    virtual void setSeed(int seed);
+    virtual Noise* zHeightMapNoise() = 0;
     const Framework::RCArray<GenerationTemplate>& getTemplates();
 };

+ 52 - 7
FactoryCraft/DimensionGenerator.cpp

@@ -25,6 +25,10 @@ void DimensionGenerator::initialize(int seed)
 {
     this->seed = seed + dimensionId;
     caveGenerator->initialize(this->seed);
+    for (auto biomGen : biomGenerators)
+    {
+        biomGen->setSeed(this->seed);
+    }
 }
 
 BiomGenerator* DimensionGenerator::zBiomGenerator(int x, int y)
@@ -62,6 +66,7 @@ void DimensionGenerator::registerBiom(
         maxTemplateAffectedPosition.z
             = MAX(maxTemplateAffectedPosition.z, t->getMaxAffectedOffset().z);
     }
+    generator->setSeed(seed);
 }
 
 Framework::RCArray<GeneratedStructure>*
@@ -86,7 +91,7 @@ DimensionGenerator::getGeneratedStructoresForArea(
         {
             BiomGenerator* biom = zBiomGenerator(x, y);
             int height = MIN_AIR_LEVEL
-                       + (int)(biom->zHeightMapNoise(seed)->getNoise(
+                       + (int)(biom->zHeightMapNoise()->getNoise(
                                    (double)(x), (double)(y), 0.0)
                                * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
             for (int z = minSearchZ; z <= maxSearchZ; z++)
@@ -122,6 +127,16 @@ DimensionGenerator::getGeneratedStructoresForArea(
 
 Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
 {
+    std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
+    double structureTime = 0;
+    double caveTime = 0;
+    double blockGenTime = 0;
+    double biomTime = 0;
+    double heightTime = 0;
+    ZeitMesser zm;
+    ZeitMesser zmGlobal;
+    zm.messungStart();
+    zmGlobal.messungStart();
     Framework::RCArray<GeneratedStructure>* structures
         = getGeneratedStructoresForArea(
             Framework::Vec3<int>(
@@ -129,20 +144,28 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
             Framework::Vec3<int>(centerX + CHUNK_SIZE / 2,
                 centerY + CHUNK_SIZE / 2,
                 WORLD_HEIGHT - 1));
-    std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
+    zm.messungEnde();
+    structureTime += zm.getSekunden();
+    zm.messungStart();
     CaveChunkGenerator* caveGen
         = caveGenerator->getGeneratorForChunk(centerX, centerY);
+    zm.messungEnde();
+    caveTime += zm.getSekunden();
     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++)
         {
+            zm.messungStart();
             BiomGenerator* biom = zBiomGenerator(x + centerX, y + centerY);
+            zm.messungEnde();
+            biomTime += zm.getSekunden();
             // TODO: use Noise interpolator for height map between different
             // bioms
+            zm.messungStart();
             int height
                 = MIN_AIR_LEVEL
-                + (int)(biom->zHeightMapNoise(seed)->getNoise(
+                + (int)(biom->zHeightMapNoise()->getNoise(
                             (double)(x + centerX), (double)(y + centerY), 0.0)
                         * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
             int maxSurfaceHeight
@@ -153,28 +176,41 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
             int actualSurfaceHeight
                 = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
                         + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
-                            * (float)biom->zHeightMapNoise(seed)->getNoise(
+                            * (float)biom->zHeightMapNoise()->getNoise(
                                 (double)(x + centerX),
                                 (double)(y + centerY),
                                 10.0)));
+            zm.messungEnde();
+            heightTime += zm.getSekunden();
             for (int z = 0; z < WORLD_HEIGHT; z++)
             {
                 Framework::Either<Block*, int> generated = BlockTypeEnum::AIR;
                 bool structureAffected = 0;
                 for (auto structure : *structures)
                 {
+                    zm.messungStart();
                     if (structure->isBlockAffected(
                             Framework::Vec3<int>(x + centerX, y + centerY, z)))
                     {
                         generated = structure->generateBlockAt(
                             Framework::Vec3<int>(x + centerX, y + centerY, z));
                         structureAffected = 1;
+                        zm.messungEnde();
+                        structureTime += zm.getSekunden();
                         break;
                     }
+                    zm.messungEnde();
+                    structureTime += zm.getSekunden();
                 }
                 if (!structureAffected)
                 {
-                    if (caveGen->isInCave(x + centerX, y + centerY, z))
+                    zm.messungStart();
+                    bool inCave
+                        = caveGen->isInCave(x + centerX, y + centerY, z);
+                    zm.messungEnde();
+                    caveTime += zm.getSekunden();
+                    zm.messungStart();
+                    if (inCave)
                         generated = biom->generateCaveBlock(
                             x + centerX, y + centerY, z);
                     else if (z < height && z >= height - actualSurfaceHeight)
@@ -183,6 +219,8 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
                     else if (z < height)
                         generated = biom->generateBelowSurfaceBlock(
                             x + centerX, y + centerY, z);
+                    zm.messungEnde();
+                    blockGenTime += zm.getSekunden();
                 }
                 if (generated.isA())
                     chunk->putBlockAt(
@@ -199,6 +237,13 @@ Chunk* DimensionGenerator::generateChunk(int centerX, int centerY)
     }
     caveGen->release();
     structures->release();
+    zmGlobal.messungEnde();
+    std::cout << "structureTime: " << structureTime << "\n";
+    std::cout << "caveTime: " << caveTime << "\n";
+    std::cout << "blockGenTime: " << blockGenTime << "\n";
+    std::cout << "biomTime: " << biomTime << "\n";
+    std::cout << "heightTime: " << heightTime << "\n";
+    std::cout << "totalTime: " << zmGlobal.getSekunden() << "\n";
     return chunk;
 }
 
@@ -210,7 +255,7 @@ Framework::Either<Block*, int> DimensionGenerator::generateBlock(
     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)->getNoise(
+               + (int)(biom->zHeightMapNoise()->getNoise(
                            (double)(location.x), (double)(location.y), 0.0)
                        * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
     int maxSurfaceHeight
@@ -221,7 +266,7 @@ Framework::Either<Block*, int> DimensionGenerator::generateBlock(
     int actualSurfaceHeight
         = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART)
                 + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART
-                    * (float)biom->zHeightMapNoise(seed)->getNoise(
+                    * (float)biom->zHeightMapNoise()->getNoise(
                         (double)(location.x), (double)(location.y), 10.0)));
     for (auto structure : *structures)
     {

+ 7 - 3
FactoryCraft/FactoryCraft.vcxproj

@@ -60,6 +60,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <UseDebugLibraries>true</UseDebugLibraries>
     <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+    <RemoteProjectRelDir>/home/kolja/projects/Server/$(ProjectName)/debug/</RemoteProjectRelDir>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <UseDebugLibraries>false</UseDebugLibraries>
@@ -77,12 +78,15 @@
   <ImportGroup Label="PropertySheets" />
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <OutDir>$(RemoteRootDir)/Server/$(ProjectName)/debug/</OutDir>
-    <IntDir>$(RemoteRootDir)/Server/$(ProjectName)/debug/</IntDir>
+    <OutDir>/home/kolja/projects/Server/$(ProjectName)/debug/</OutDir>
+    <IntDir>/home/kolja/projects/Server/$(ProjectName)/debug/</IntDir>
     <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/debug</RemoteProjectDir>
     <IncludePath>..\..\..\..\..\Allgemein\Framework;../../../Framework/debug;..\..\..\..\..\Allgemein\Network\Network;../../../Network/debug/Network;../../../KsgScript/debug/KsgScript;..\..\..\..\..\Allgemein\KSGScript\KSGScript\Include;$(IncludePath)</IncludePath>
     <RemoteTargetPath>$(RemoteProjectDir)/$(TargetName)$(TargetExt)</RemoteTargetPath>
     <RemoteLinkLocalCopyOutput>true</RemoteLinkLocalCopyOutput>
+    <RemoteIntRelDir>/home/kolja/projects/Server/$(ProjectName)/debug/</RemoteIntRelDir>
+    <RemoteOutRelDir>/home/kolja/projects/Server/$(ProjectName)/debug/</RemoteOutRelDir>
+    <RemoteDeployDir>/home/kolja/projects/Server/$(ProjectName)/debug/</RemoteDeployDir>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <OutDir>$(RemoteRootDir)/Server/$(ProjectName)/release/</OutDir>
@@ -225,7 +229,7 @@
     <ClCompile>
       <CppLanguageStandard>c++17</CppLanguageStandard>
       <AdditionalIncludeDirectories>../../../Framework/debug;../../../Network/debug/Network;../../../KsgScript/debug/KsgScript</AdditionalIncludeDirectories>
-      <ObjectFileName>/home/kolja/projects/Server/FactoryCraft/debug/%(filename).o</ObjectFileName>
+      <ObjectFileName>%(filename).o</ObjectFileName>
     </ClCompile>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+ 45 - 8
FactoryCraft/GrasslandBiom.cpp

@@ -10,27 +10,30 @@
 GrasslandBiom::GrasslandBiom()
     : BiomGenerator()
 {
-    addTemplateGenerator(new TreeTemplate(0.02f,
+    addTemplateGenerator(new TreeTemplate(0.002f,
         BlockTypeEnum::WOOD_BIRCH,
         BlockTypeEnum::LEAVES_WOOD_BIRCH,
         8,
         15));
-    addTemplateGenerator(new TreeTemplate(0.01f,
+    addTemplateGenerator(new TreeTemplate(0.001f,
         BlockTypeEnum::WOOD_BEECH,
         BlockTypeEnum::LEAVES_WOOD_BEECH,
         8,
         13));
-    addTemplateGenerator(new TreeTemplate(0.005f,
+    addTemplateGenerator(new TreeTemplate(0.0005f,
         BlockTypeEnum::WOOD_OAK,
         BlockTypeEnum::LEAVES_WOOD_OAK,
         10,
         15));
-    addTemplateGenerator(new TreeTemplate(0.0025f,
+    addTemplateGenerator(new TreeTemplate(0.00025f,
         BlockTypeEnum::WOOD_PINE,
         BlockTypeEnum::LEAVES_WOOD_PINE,
         15,
         24));
     heightNoise = 0;
+    undergroundDirdNoise = 0;
+    surfaceSandNoise = 0;
+    undergroundGravelNoise = 0;
 }
 
 GrasslandBiom::~GrasslandBiom()
@@ -41,14 +44,31 @@ GrasslandBiom::~GrasslandBiom()
 Framework::Either<Block*, int> GrasslandBiom::generateSurfaceBlock(
     int x, int y, int z)
 {
-    if (((float)rand() / (float)RAND_MAX) < 0.05f) // TODO: use random noise
-        return BlockTypeEnum::STONE_COBBLE;
+    if (surfaceSandNoise->getNoise((double)x, (double)y, (double)z) < 0.35)
+    {
+        return BlockTypeEnum::SAND;
+    }
+    if (undergroundGravelNoise->getNoise((double)x, (double)y, (double)z)
+        < 0.35)
+    {
+        return BlockTypeEnum::GRAVEL;
+    }
     return BlockTypeEnum::DIRT;
 }
 
 Framework::Either<Block*, int> GrasslandBiom::generateBelowSurfaceBlock(
     int x, int y, int z)
 {
+    if (undergroundDirdNoise->getNoise((double)x, (double)y, (double)z)
+        < 0.35)
+    {
+        return BlockTypeEnum::DIRT;
+    }
+    if (undergroundGravelNoise->getNoise((double)x, (double)y, (double)z)
+        < 0.35)
+    {
+        return BlockTypeEnum::GRAVEL;
+    }
     return BlockTypeEnum::STONE;
 }
 
@@ -58,13 +78,30 @@ Framework::Either<Block*, int> GrasslandBiom::generateCaveBlock(
     return BlockTypeEnum::AIR;
 }
 
-Noise* GrasslandBiom::zHeightMapNoise(int seed)
+void GrasslandBiom::setSeed(int seed)
 {
-    if (heightNoise) return heightNoise;
+    BiomGenerator::setSeed(seed);
+    if (heightNoise) heightNoise->release();
     FastNoiseLite* noise = new FastNoiseLite(seed);
     noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
     FastNoiseWrapper* wrapper = new FastNoiseWrapper(noise, seed);
     wrapper->setMultiplier(0.2f);
     heightNoise = wrapper;
+    noise = new FastNoiseLite(seed);
+    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
+    noise->SetFrequency(0.15f);
+    undergroundDirdNoise = new FastNoiseWrapper(noise, seed);
+    noise = new FastNoiseLite(seed + 1);
+    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
+    noise->SetFrequency(0.125f);
+    undergroundGravelNoise = new FastNoiseWrapper(noise, seed + 1);
+    noise = new FastNoiseLite(seed + 2);
+    noise->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
+    noise->SetFrequency(0.1f);
+    surfaceSandNoise = new FastNoiseWrapper(noise, seed + 2);
+}
+
+Noise* GrasslandBiom::zHeightMapNoise()
+{
     return heightNoise;
 }

+ 7 - 1
FactoryCraft/GrasslandBiom.h

@@ -6,6 +6,11 @@
 class GrasslandBiom : public BiomGenerator
 {
     Noise* heightNoise;
+    Noise* undergroundDirdNoise;
+    Noise* surfaceSandNoise;
+    Noise* undergroundGravelNoise;
+    // TODO: Noise* anySmallOreNoise;
+	// TODO: add water rivers
 
 public:
     GrasslandBiom();
@@ -16,5 +21,6 @@ public:
         int x, int y, int z) override;
     Framework::Either<Block*, int> generateCaveBlock(
         int x, int y, int z) override;
-    Noise* zHeightMapNoise(int seed) override;
+    Noise* zHeightMapNoise() override;
+    void setSeed(int seed) override;
 };

+ 3 - 4
FactoryCraft/RandNoise.cpp

@@ -12,9 +12,9 @@ RandNoise::RandNoise(int seed)
       seed(seed)
 {
     srand(seed);
-    table = new short[RandNoiseTableSize];
+    table = new unsigned short[RandNoiseTableSize];
     for (int i = 0; i < RandNoiseTableSize; i++)
-        table[i] = (short)rand();
+        table[i] = (unsigned short)(rand() % 0xFFFF);
 }
 
 RandNoise::~RandNoise()
@@ -33,6 +33,5 @@ double RandNoise::getNoise(double x, double y, double z)
     index = abs(table[index] + (int)x) % RandNoiseTableSize;
     index = abs(table[index] + (int)y) % RandNoiseTableSize;
     index = abs(table[index] + (int)z) % RandNoiseTableSize;
-    return (double)table[index]
-         / RAND_MAX;
+    return (double)table[index] / 0xFFFF;
 }

+ 1 - 1
FactoryCraft/RandNoise.h

@@ -10,7 +10,7 @@ class FastNoiseWrapper;
 class RandNoise : public Noise
 {
 private:
-    short *table;
+    unsigned short* table;
     int seed;
 
 public:

+ 23 - 8
FactoryCraft/WormCaveGenerator.cpp

@@ -4,6 +4,10 @@
 #include "Game.h"
 #include "RandNoise.h"
 
+NoiseWorm3D::NoiseWorm3D()
+    : ReferenceCounter()
+{}
+
 NoiseWorm3D::NoiseWorm3D(Noise* pitch,
     Noise* yaw,
     Noise* size,
@@ -57,8 +61,9 @@ Framework::Punkt NoiseWorm3D::getStartChunkCenter()
     return startChunk;
 }
 
-bool NoiseWorm3D::isChunkAffected(int x, int y)
+NoiseWorm3D *NoiseWorm3D::getPartAffectedByChunk(int x, int y)
 {
+    NoiseWorm3D* result = 0;
     if (x - CHUNK_SIZE / 2 <= maxAffected.x
         && x + CHUNK_SIZE / 2 >= minAffected.x
         && y - CHUNK_SIZE / 2 <= maxAffected.y
@@ -69,15 +74,22 @@ bool NoiseWorm3D::isChunkAffected(int x, int y)
         while (pi && si)
         {
             if ((Vec2<float>((float)x, (float)y)
-                    - Vec2<float>(pi.val().x, pi.val().y))
+                - Vec2<float>(pi.val().x, pi.val().y))
                     .getLengthSq()
                 < (si.val() + CHUNK_SIZE / 2) * (si.val() + CHUNK_SIZE / 2))
-                return 1;
+            {
+                if (result == 0)
+                {
+                    result = new NoiseWorm3D();
+                }
+                result->keyPoints.add(pi.val());
+                result->size.add(si.val());
+            }
             ++pi;
             ++si;
         }
     }
-    return 0;
+    return result;
 }
 
 bool NoiseWorm3D::isInside(int x, int y, int z)
@@ -86,8 +98,8 @@ bool NoiseWorm3D::isInside(int x, int y, int z)
     auto si = size.begin();
     while (pi && si)
     {
-        if (Vec3<float>((float)x, (float)y, (float)z).abstand(pi.val())
-            < si.val())
+        if (Vec3<float>((float)x, (float)y, (float)z).abstandSq(pi.val())
+            < si.val() * si.val())
             return 1;
         ++pi;
         ++si;
@@ -207,8 +219,11 @@ CaveChunkGenerator* WormCaveGenerator::getGeneratorForChunk(int x, int y)
         {
             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()));
+            if (worm)
+            {
+                NoiseWorm3D* cuttedWorm = worm->getPartAffectedByChunk(x, y);
+                if (cuttedWorm) affected.add(cuttedWorm);
+            }
         }
     }
     return new WormCaveChunkGenerator(affected);

+ 2 - 1
FactoryCraft/WormCaveGenerator.h

@@ -16,6 +16,7 @@ private:
 
     Framework::Array<Framework::Vec3<float>> keyPoints;
     Framework::Array<float> size;
+    NoiseWorm3D();
 
 public:
     NoiseWorm3D(Noise* pitch,
@@ -26,7 +27,7 @@ public:
         int minRad,
         int maxRad);
     Framework::Punkt getStartChunkCenter();
-    bool isChunkAffected(int x, int y);
+    NoiseWorm3D* getPartAffectedByChunk(int x, int y);
     bool isInside(int x, int y, int z);
 };
 

+ 1 - 1
Windows Version/Start.cpp

@@ -98,7 +98,7 @@ int main()
     wrapper = new FastNoiseWrapper(n, 0);
     wrapper = new ShapedNoise(wrapper);
     ((ShapedNoise*)wrapper)->setNeighborOffset(4.f);
-
+    wrapper = new RandNoise(34255);
 
     img = new Bild();
     img->neuBild(800, 800, 0xFF000000);