1
0
Fork 0

Added Steppy height generator.

This commit is contained in:
Mattes D 2015-03-01 12:13:39 +01:00
parent a22a81ef4b
commit 780a9ae9d1
3 changed files with 409 additions and 1 deletions

View File

@ -1036,7 +1036,7 @@ protected:
////////////////////////////////////////////////////////////////////////////////
// cBioGenGrown:
// cBioGenProtGrown:
class cBioGenProtGrown:
public cBiomeGen

View File

@ -10,6 +10,66 @@
#include "DistortedHeightmap.h"
#include "EndGen.h"
#include "Noise3DGenerator.h"
#include "ProtIntGen.h"
////////////////////////////////////////////////////////////////////////////////
// cHeiGenSteppy:
class cHeiGenSteppy:
public cTerrainHeightGen
{
public:
cHeiGenSteppy(int a_Seed) :
m_Seed(a_Seed)
{
m_Gen =
std::make_shared<cProtIntGenWeightAvg<16, 1, 0>>(
std::make_shared<cProtIntGenSmooth> (a_Seed + 1,
std::make_shared<cProtIntGenZoom> (a_Seed + 2,
std::make_shared<cProtIntGenSmooth> (a_Seed + 3,
std::make_shared<cProtIntGenZoom> (a_Seed + 4,
std::make_shared<cProtIntGenAddRnd> (a_Seed + 5, 1,
std::make_shared<cProtIntGenSmooth> (a_Seed + 6,
std::make_shared<cProtIntGenZoom> (a_Seed + 7,
std::make_shared<cProtIntGenRndBetween> (a_Seed + 8, 60,
std::make_shared<cProtIntGenAddRnd> (a_Seed + 9, 1,
std::make_shared<cProtIntGenSmooth> (a_Seed + 1,
std::make_shared<cProtIntGenZoom> (a_Seed + 2,
std::make_shared<cProtIntGenRndBetween> (a_Seed + 3, 60,
std::make_shared<cProtIntGenSmooth> (a_Seed + 4,
std::make_shared<cProtIntGenZoom> (a_Seed + 5,
std::make_shared<cProtIntGenRndBetween> (a_Seed + 6, 60,
std::make_shared<cProtIntGenRndChoice> (a_Seed + 7, 10, 50, 50,
std::make_shared<cProtIntGenSmooth> (a_Seed + 8,
std::make_shared<cProtIntGenZoom> (a_Seed + 9,
std::make_shared<cProtIntGenRndChoice> (a_Seed + 1, 10, 50, 50,
std::make_shared<cProtIntGenAddRnd> (a_Seed + 2, 2,
std::make_shared<cProtIntGenZoom> (a_Seed + 3,
std::make_shared<cProtIntGenZoom> (a_Seed + 4,
std::make_shared<cProtIntGenChoice> (a_Seed + 5, 10)
)))))))))))))))))))))));
}
// cTerrainHeightGen overrides:
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override
{
int heights[cChunkDef::Width * cChunkDef::Width];
m_Gen->GetInts(a_ChunkX * cChunkDef::Width, a_ChunkZ * cChunkDef::Width, cChunkDef::Width, cChunkDef::Width, heights);
for (auto i = 0; i < ARRAYCOUNT(heights); i++)
{
a_HeightMap[i] = static_cast<HEIGHTTYPE>(std::max(std::min(60 + heights[i], cChunkDef::Height - 60), 40));
}
}
protected:
int m_Seed;
SharedPtr<cProtIntGen> m_Gen;
};
@ -821,6 +881,10 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB
// Return an empty pointer, the caller will create the proper generator:
return cTerrainHeightGenPtr();
}
else if (NoCaseCompare(HeightGenName, "Steppy") == 0)
{
res = std::make_shared<cHeiGenSteppy>(a_Seed);
}
else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
{
// Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it

View File

@ -318,6 +318,350 @@ protected:
/** Averages the values of the underlying 2 * 2 neighbors. */
class cProtIntGenAvgValues :
public cProtIntGen
{
typedef cProtIntGen super;
public:
cProtIntGenAvgValues(Underlying a_Underlying) :
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
int lowerSizeX = a_SizeX + 1;
int lowerSizeZ = a_SizeZ + 1;
ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize);
int lowerData[m_BufferSize];
m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerData);
// Average - add all 4 "neighbors" and divide by 4:
for (int z = 0; z < a_SizeZ; z++)
{
for (int x = 0; x < a_SizeX; x++)
{
int idxLower = x + lowerSizeX * z;
a_Values[x + a_SizeX * z] = (
lowerData[idxLower] + lowerData[idxLower + 1] +
lowerData[idxLower + lowerSizeX] + lowerData[idxLower + lowerSizeX + 1]
) / 4;
}
}
}
protected:
Underlying m_Underlying;
};
/** Averages the values of the underlying 4 * 4 neighbors. */
class cProtIntGenAvg4Values :
public cProtIntGen
{
typedef cProtIntGen super;
public:
cProtIntGenAvg4Values(Underlying a_Underlying) :
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
int lowerSizeX = a_SizeX + 4;
int lowerSizeZ = a_SizeZ + 4;
ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize);
int lowerData[m_BufferSize];
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData);
// Calculate the weighted average of all 16 "neighbors":
for (int z = 0; z < a_SizeZ; z++)
{
for (int x = 0; x < a_SizeX; x++)
{
int idxLower1 = x + lowerSizeX * z;
int idxLower2 = idxLower1 + lowerSizeX;
int idxLower3 = idxLower1 + 2 * lowerSizeX;
int idxLower4 = idxLower1 + 3 * lowerSizeX;
a_Values[x + a_SizeX * z] = (
1 * lowerData[idxLower1] + 2 * lowerData[idxLower1 + 1] + 2 * lowerData[idxLower1 + 2] + 1 * lowerData[idxLower1 + 3] +
2 * lowerData[idxLower2] + 32 * lowerData[idxLower2 + 1] + 32 * lowerData[idxLower2 + 2] + 2 * lowerData[idxLower2 + 3] +
2 * lowerData[idxLower3] + 32 * lowerData[idxLower3 + 1] + 32 * lowerData[idxLower3 + 2] + 2 * lowerData[idxLower3 + 3] +
1 * lowerData[idxLower4] + 2 * lowerData[idxLower4 + 1] + 2 * lowerData[idxLower4 + 2] + 1 * lowerData[idxLower4 + 3]
) / 148;
}
}
}
protected:
Underlying m_Underlying;
};
/** Averages the values of the underlying 3 * 3 neighbors with custom weight. */
template <int WeightCenter, int WeightCardinal, int WeightDiagonal>
class cProtIntGenWeightAvg :
public cProtIntGen
{
typedef cProtIntGen super;
public:
cProtIntGenWeightAvg(Underlying a_Underlying) :
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
int lowerSizeX = a_SizeX + 3;
int lowerSizeZ = a_SizeZ + 3;
ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize);
int lowerData[m_BufferSize];
m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerData);
// Calculate the weighted average the neighbors:
for (int z = 0; z < a_SizeZ; z++)
{
for (int x = 0; x < a_SizeX; x++)
{
int idxLower1 = x + lowerSizeX * z;
int idxLower2 = idxLower1 + lowerSizeX;
int idxLower3 = idxLower1 + 2 * lowerSizeX;
a_Values[x + a_SizeX * z] = (
WeightDiagonal * lowerData[idxLower1] + WeightCardinal * lowerData[idxLower1 + 1] + WeightDiagonal * lowerData[idxLower1 + 2] +
WeightCardinal * lowerData[idxLower2] + WeightCenter * lowerData[idxLower2 + 1] + WeightCardinal * lowerData[idxLower2 + 2] +
WeightDiagonal * lowerData[idxLower3] + WeightCardinal * lowerData[idxLower3 + 1] + WeightDiagonal * lowerData[idxLower3 + 2]
) / (4 * WeightDiagonal + 4 * WeightCardinal + WeightCenter);
}
}
}
protected:
Underlying m_Underlying;
};
/** Replaces random values of the underlying data with random integers in the specified range [Min .. Min + Range). */
class cProtIntGenRndChoice :
public cProtIntGenWithNoise
{
typedef cProtIntGenWithNoise super;
public:
cProtIntGenRndChoice(int a_Seed, int a_ChancePct, int a_Min, int a_Range, Underlying a_Underlying) :
super(a_Seed),
m_ChancePct(a_ChancePct),
m_Min(a_Min),
m_Range(a_Range),
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values);
// Replace random values:
for (int z = 0; z < a_SizeZ; z++)
{
int BaseZ = a_MinZ + z;
for (int x = 0; x < a_SizeX; x++)
{
if (((super::m_Noise.IntNoise2DInt(BaseZ, a_MinX + x) / 13) % 101) < m_ChancePct)
{
a_Values[x + a_SizeX * z] = m_Min + (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % m_Range;
}
} // for x
} // for z
}
protected:
int m_ChancePct;
int m_Min;
int m_Range;
Underlying m_Underlying;
};
/** Adds a random value in range [-a_HalfRange, +a_HalfRange] to each of the underlying values. */
class cProtIntGenAddRnd :
public cProtIntGenWithNoise
{
typedef cProtIntGenWithNoise super;
public:
cProtIntGenAddRnd(int a_Seed, int a_HalfRange, Underlying a_Underlying) :
super(a_Seed),
m_Range(a_HalfRange * 2 + 1),
m_HalfRange(a_HalfRange),
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values);
// Add the random values:
for (int z = 0; z < a_SizeZ; z++)
{
int NoiseZ = a_MinZ + z;
for (int x = 0; x < a_SizeX; x++)
{
int noiseVal = ((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % m_Range) - m_HalfRange;
a_Values[x + z * a_SizeX] += noiseVal;
}
}
}
protected:
int m_Range;
int m_HalfRange;
Underlying m_Underlying;
};
/** Replaces random underlying values with the average of the neighbors. */
class cProtIntGenRndAvg :
public cProtIntGenWithNoise
{
typedef cProtIntGenWithNoise super;
public:
cProtIntGenRndAvg(int a_Seed, int a_AvgChancePct, Underlying a_Underlying) :
super(a_Seed),
m_AvgChancePct(a_AvgChancePct),
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
int lowerSizeX = a_SizeX + 2;
int lowerSizeZ = a_SizeZ + 2;
ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize);
int lowerData[m_BufferSize];
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData);
// Average random values:
for (int z = 0; z < a_SizeZ; z++)
{
int NoiseZ = a_MinZ + z;
for (int x = 0; x < a_SizeX; x++)
{
int idxLower = x + 1 + lowerSizeX * (z + 1);
if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 100) > m_AvgChancePct)
{
// Average the 4 neighbors:
a_Values[x + z * a_SizeX] = (
lowerData[idxLower - 1] + lowerData[idxLower + 1] +
lowerData[idxLower - lowerSizeX] + lowerData[idxLower + lowerSizeX]
) / 4;
}
else
{
// Keep the underlying value:
a_Values[x + z * a_SizeX] = lowerData[idxLower];
}
}
}
}
protected:
int m_AvgChancePct;
Underlying m_Underlying;
};
/** Replaces random underlying values with a random value in between the max and min of the neighbors. */
class cProtIntGenRndBetween :
public cProtIntGenWithNoise
{
typedef cProtIntGenWithNoise super;
public:
cProtIntGenRndBetween(int a_Seed, int a_AvgChancePct, Underlying a_Underlying) :
super(a_Seed),
m_AvgChancePct(a_AvgChancePct),
m_Underlying(a_Underlying)
{
}
virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override
{
// Generate the underlying values:
int lowerSizeX = a_SizeX + 2;
int lowerSizeZ = a_SizeZ + 2;
ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize);
int lowerData[m_BufferSize];
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData);
// Average random values:
for (int z = 0; z < a_SizeZ; z++)
{
int NoiseZ = a_MinZ + z;
for (int x = 0; x < a_SizeX; x++)
{
int idxLower = x + 1 + lowerSizeX * (z + 1);
if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 100) > m_AvgChancePct)
{
// Chose a value in between the min and max neighbor:
int min = std::min(std::min(lowerData[idxLower - 1], lowerData[idxLower + 1]), std::min(lowerData[idxLower - lowerSizeX], lowerData[idxLower + lowerSizeX]));
int max = std::max(std::max(lowerData[idxLower - 1], lowerData[idxLower + 1]), std::max(lowerData[idxLower - lowerSizeX], lowerData[idxLower + lowerSizeX]));
a_Values[x + z * a_SizeX] = min + ((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ + 10) / 7) % (max - min + 1));
}
else
{
// Keep the underlying value:
a_Values[x + z * a_SizeX] = lowerData[idxLower];
}
}
}
}
protected:
int m_AvgChancePct;
Underlying m_Underlying;
};
/** Converts land biomes at the edge of an ocean into the respective beach biome. */
class cProtIntGenBeaches :
public cProtIntGen