summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Generating/EndGen.cpp148
-rw-r--r--src/Generating/EndGen.h27
2 files changed, 89 insertions, 86 deletions
diff --git a/src/Generating/EndGen.cpp b/src/Generating/EndGen.cpp
index 4e5e1a809..72dc180e7 100644
--- a/src/Generating/EndGen.cpp
+++ b/src/Generating/EndGen.cpp
@@ -34,28 +34,41 @@ enum
cEndGen::cEndGen(int a_Seed) :
m_Seed(a_Seed),
- m_IslandSizeX(256),
- m_IslandSizeY(96),
- m_IslandSizeZ(256),
+ m_Perlin(a_Seed),
+ m_VoidOffsetNoise(a_Seed + 1000),
+ m_AirThresholdMainIsland(0.0f),
+ m_AirThresholdOtherIslands(0.5f),
+ m_MainIslandSize(450),
+ m_BaseHeight(64),
+ m_TerrainTopMultiplier(10),
+ m_TerrainBottomMultiplier(40),
+ m_VoidOffsetNoiseMultiplier(50),
m_FrequencyX(80),
m_FrequencyY(80),
- m_FrequencyZ(80),
- m_LastChunkCoords(0x7fffffff, 0x7fffffff) // Use dummy coords that won't ever be used by real chunks
+ m_FrequencyZ(80)
{
m_Perlin.AddOctave(1, 1);
m_Perlin.AddOctave(2, 0.5);
m_Perlin.AddOctave(4, 0.25);
+
+ m_VoidOffsetNoise.AddOctave(1, 1);
+ m_VoidOffsetNoise.AddOctave(2, 0.5);
+ m_VoidOffsetNoise.AddOctave(4, 0.25);
}
-void cEndGen::InitializeCompoGen(cIniFile & a_IniFile)
+void cEndGen::InitializeShapeGen(cIniFile & a_IniFile)
{
- m_IslandSizeX = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeX", m_IslandSizeX);
- m_IslandSizeY = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeY", m_IslandSizeY);
- m_IslandSizeZ = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeZ", m_IslandSizeZ);
+ m_AirThresholdMainIsland = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "EndGenAirThresholdMainIsland", m_AirThresholdMainIsland));
+ m_AirThresholdOtherIslands = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "EndGenAirThresholdOtherIslands", m_AirThresholdOtherIslands));
+ m_MainIslandSize = a_IniFile.GetValueSetI("Generator", "EndGenMainIslandSize", m_MainIslandSize);
+ m_BaseHeight = a_IniFile.GetValueSetI("Generator", "EndGenBaseHeight", m_BaseHeight);
+ m_TerrainTopMultiplier = a_IniFile.GetValueSetI("Generator", "EndGenTerrainTopMultipler", m_TerrainTopMultiplier);
+ m_TerrainBottomMultiplier = a_IniFile.GetValueSetI("Generator", "EndGenTerrainBottomMultiplier", m_TerrainBottomMultiplier);
+ m_VoidOffsetNoiseMultiplier = a_IniFile.GetValueSetI("Generator", "EndGenVoidOffsetNoiseMultiplier", m_VoidOffsetNoiseMultiplier);
m_FrequencyX = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "EndGenFrequencyX", m_FrequencyX));
m_FrequencyY = static_cast<NOISE_DATATYPE>(a_IniFile.GetValueSetF("Generator", "EndGenFrequencyY", m_FrequencyY));
@@ -66,83 +79,78 @@ void cEndGen::InitializeCompoGen(cIniFile & a_IniFile)
-void cEndGen::PrepareState(cChunkCoords a_ChunkCoords)
+void cEndGen::GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape)
{
- if (m_LastChunkCoords == a_ChunkCoords)
+ for (size_t i = 0; i < ARRAYCOUNT(a_Shape); i++)
{
- return;
+ a_Shape[i] = 0;
}
- m_LastChunkCoords = a_ChunkCoords;
-
- GenerateNoiseArray();
-}
-
+ NOISE_DATATYPE NoiseData[cChunkDef::Width * cChunkDef::Width];
+ NOISE_DATATYPE VoidOffsetData[cChunkDef::Width * cChunkDef::Width];
+ NOISE_DATATYPE Workspace[cChunkDef::Width * cChunkDef::Width];
+ NOISE_DATATYPE StartX = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkX * cChunkDef::Width) / m_FrequencyX;
+ NOISE_DATATYPE EndX = static_cast<NOISE_DATATYPE>((a_ChunkCoords.m_ChunkX + 1) * cChunkDef::Width) / m_FrequencyX;
+ NOISE_DATATYPE StartZ = static_cast<NOISE_DATATYPE>(a_ChunkCoords.m_ChunkZ * cChunkDef::Width) / m_FrequencyZ;
+ NOISE_DATATYPE EndZ = static_cast<NOISE_DATATYPE>((a_ChunkCoords.m_ChunkZ + 1) * cChunkDef::Width) / m_FrequencyZ;
+ m_Perlin.Generate2D(NoiseData, cChunkDef::Width, cChunkDef::Width, StartX, EndX, StartZ, EndZ, Workspace);
+ m_VoidOffsetNoise.Generate2D(VoidOffsetData, cChunkDef::Width, cChunkDef::Width, StartX, EndX, StartZ, EndZ, Workspace);
-
-
-void cEndGen::GenerateNoiseArray(void)
-{
- NOISE_DATATYPE NoiseData[DIM_X * DIM_Y * DIM_Z]; // [x + DIM_X * z + DIM_X * DIM_Z * y]
- NOISE_DATATYPE Workspace[DIM_X * DIM_Y * DIM_Z]; // [x + DIM_X * z + DIM_X * DIM_Z * y]
-
- // Generate the downscaled noise:
- NOISE_DATATYPE StartX = static_cast<NOISE_DATATYPE>(m_LastChunkCoords.m_ChunkX * cChunkDef::Width) / m_FrequencyX;
- NOISE_DATATYPE EndX = static_cast<NOISE_DATATYPE>((m_LastChunkCoords.m_ChunkX + 1) * cChunkDef::Width) / m_FrequencyX;
- NOISE_DATATYPE StartZ = static_cast<NOISE_DATATYPE>(m_LastChunkCoords.m_ChunkZ * cChunkDef::Width) / m_FrequencyZ;
- NOISE_DATATYPE EndZ = static_cast<NOISE_DATATYPE>((m_LastChunkCoords.m_ChunkZ + 1) * cChunkDef::Width) / m_FrequencyZ;
- NOISE_DATATYPE StartY = 0;
- NOISE_DATATYPE EndY = static_cast<NOISE_DATATYPE>(257) / m_FrequencyY;
- m_Perlin.Generate3D(NoiseData, DIM_X, DIM_Z, DIM_Y, StartX, EndX, StartZ, EndZ, StartY, EndY, Workspace);
-
- // Add distance:
- int idx = 0;
- for (int y = 0; y < DIM_Y; y++)
+ for (int z = 0; z < cChunkDef::Width; z++)
{
- NOISE_DATATYPE ValY = static_cast<NOISE_DATATYPE>(2 * INTERPOL_Y * y - m_IslandSizeY) / m_IslandSizeY;
- ValY = ValY * ValY;
- for (int z = 0; z < DIM_Z; z++)
+ for (int x = 0; x < cChunkDef::Width; x++)
{
- NOISE_DATATYPE ValZ = static_cast<NOISE_DATATYPE>(m_LastChunkCoords.m_ChunkZ * cChunkDef::Width + (z * cChunkDef::Width / (DIM_Z - 1))) / m_IslandSizeZ;
- ValZ = ValZ * ValZ;
- for (int x = 0; x < DIM_X; x++)
- {
- // NOISE_DATATYPE ValX = StartX + (EndX - StartX) * x / (DIM_X - 1);
- NOISE_DATATYPE ValX = static_cast<NOISE_DATATYPE>(m_LastChunkCoords.m_ChunkX * cChunkDef::Width + (x * cChunkDef::Width / (DIM_X - 1))) / m_IslandSizeX;
- ValX = ValX * ValX;
- NoiseData[idx++] += ValX + ValZ + ValY;
- } // for x
- } // for z
- } // for y
-
- // Upscale into real chunk size:
- LinearUpscale3DArray(NoiseData, DIM_X, DIM_Z, DIM_Y, m_NoiseArray, INTERPOL_X, INTERPOL_Z, INTERPOL_Y);
-}
-
-
+ NOISE_DATATYPE noise = NoiseData[z * cChunkDef::Width + x];
+ // The distance from spawn is used to create the void between the main island and the other islands.
+ double distanceFromSpawn = cChunkDef::RelativeToAbsolute({ x, 0, z }, a_ChunkCoords).Length();
+ // The main island can get a different airthreshold. This way the other island can be more sparse while the main island
+ // is one big island.
+ if (distanceFromSpawn > m_MainIslandSize)
+ {
+ if (noise <= m_AirThresholdOtherIslands)
+ {
+ continue;
+ }
+ noise -= m_AirThresholdOtherIslands;
+ }
+ else
+ {
+ if (noise <= m_AirThresholdMainIsland)
+ {
+ continue;
+ }
+ noise -= m_AirThresholdMainIsland;
+ }
+ NOISE_DATATYPE voidOffset = VoidOffsetData[z * cChunkDef::Width + x];
-void cEndGen::GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape)
-{
- PrepareState(a_ChunkCoords);
- int MaxY = std::min(static_cast<int>(1.75 * m_IslandSizeY + 1), cChunkDef::Height - 1);
- for (int z = 0; z < cChunkDef::Width; z++)
- {
- for (int x = 0; x < cChunkDef::Width; x++)
- {
- for (int y = 0; y < MaxY; y++)
+ double maxHeightLimit;
+ if (distanceFromSpawn > m_MainIslandSize * 3)
{
- a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= 0) ? 1 : 0;
+ // The distance from spawn is so big we don't need to calculate the max height anymore.
+ // In fact, if we don't cut it off somewhere there is a chance the maxheight gets too big which
+ // can cause corrupted looking terrain.
+ maxHeightLimit = static_cast<float>(cChunkDef::Height);
}
- for (int y = MaxY; y < cChunkDef::Height; y++)
+ else
{
- a_Shape[y + x * 256 + z * 256 * 16] = 0;
+ // Create a void between the main island and the other island using the formula 'x^3 - 3 * x' where x is distance from spawn.
+ double pow = std::pow((distanceFromSpawn - m_MainIslandSize) / m_MainIslandSize, 3);
+ double mult = 3 * ((distanceFromSpawn - m_MainIslandSize) / m_MainIslandSize);
+ maxHeightLimit = Clamp((pow - mult) * 100 + static_cast<double>(voidOffset) * m_VoidOffsetNoiseMultiplier, 0.0, static_cast<double>(cChunkDef::Height));
}
- } // for x
- } // for z
+ int maxHeight = static_cast<int>(Clamp(m_BaseHeight + static_cast<double>(noise) * m_TerrainTopMultiplier, 0.0, maxHeightLimit));
+ int minHeight = static_cast<int>(Clamp(m_BaseHeight - static_cast<double>(noise) * m_TerrainBottomMultiplier, 0.0, static_cast<double>(cChunkDef::Height)));
+
+ for (int y = minHeight; y < maxHeight; y++)
+ {
+ a_Shape[y + x * 256 + z * 256 * 16] = 1;
+ }
+ }
+ }
}
diff --git a/src/Generating/EndGen.h b/src/Generating/EndGen.h
index c1c6f00b6..bd1debdeb 100644
--- a/src/Generating/EndGen.h
+++ b/src/Generating/EndGen.h
@@ -30,33 +30,28 @@ protected:
/** The Perlin noise used for generating */
cPerlinNoise m_Perlin;
+ cPerlinNoise m_VoidOffsetNoise;
- // XYZ size of the "island", in blocks:
- int m_IslandSizeX;
- int m_IslandSizeY;
- int m_IslandSizeZ;
+ NOISE_DATATYPE m_AirThresholdMainIsland;
+ NOISE_DATATYPE m_AirThresholdOtherIslands;
+ int m_MainIslandSize;
+ int m_BaseHeight;
+ int m_TerrainTopMultiplier;
+ int m_TerrainBottomMultiplier;
+ int m_VoidOffsetNoiseMultiplier;
// XYZ Frequencies of the noise functions:
NOISE_DATATYPE m_FrequencyX;
NOISE_DATATYPE m_FrequencyY;
NOISE_DATATYPE m_FrequencyZ;
- // Noise array for the last chunk (in the noise range)
- cChunkCoords m_LastChunkCoords;
- NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // x + 17 * z + 17 * 17 * y
-
-
- /** Unless the LastChunk coords are equal to coords given, prepares the internal state (noise array) */
- void PrepareState(cChunkCoords a_ChunkCoords);
-
- /** Generates the m_NoiseArray array for the current chunk */
- void GenerateNoiseArray(void);
-
// cTerrainShapeGen overrides:
virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override;
// cTerrainCompositionGen overrides:
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override;
- virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
+
+ // cTerrainShapeGen overrides:
+ virtual void InitializeShapeGen(cIniFile & a_IniFile) override;
} ;