Bulk clearing of whitespace
This commit is contained in:
@@ -101,26 +101,26 @@ void cBioGenCache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a
|
||||
}
|
||||
// Found it in the cache
|
||||
size_t Idx = m_CacheOrder[i];
|
||||
|
||||
|
||||
// Move to front:
|
||||
for (size_t j = i; j > 0; j--)
|
||||
{
|
||||
m_CacheOrder[j] = m_CacheOrder[j - 1];
|
||||
}
|
||||
m_CacheOrder[0] = Idx;
|
||||
|
||||
|
||||
// Use the cached data:
|
||||
memcpy(a_BiomeMap, m_CacheData[Idx].m_BiomeMap, sizeof(a_BiomeMap));
|
||||
|
||||
|
||||
m_NumHits++;
|
||||
m_TotalChain += i;
|
||||
return;
|
||||
} // for i - cache
|
||||
|
||||
|
||||
// Not in the cache:
|
||||
m_NumMisses++;
|
||||
m_BioGenToCache->GenBiomes(a_ChunkX, a_ChunkZ, a_BiomeMap);
|
||||
|
||||
|
||||
// Insert it as the first item in the MRU order:
|
||||
size_t Idx = m_CacheOrder[m_CacheSize - 1];
|
||||
for (size_t i = m_CacheSize - 1; i > 0; i--)
|
||||
@@ -346,7 +346,7 @@ void cBioGenDistortedVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::B
|
||||
{
|
||||
int BaseZ = cChunkDef::Width * a_ChunkZ;
|
||||
int BaseX = cChunkDef::Width * a_ChunkX;
|
||||
|
||||
|
||||
// Distortions for linear interpolation:
|
||||
int DistortX[cChunkDef::Width + 1][cChunkDef::Width + 1];
|
||||
int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1];
|
||||
@@ -354,10 +354,10 @@ void cBioGenDistortedVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::B
|
||||
{
|
||||
Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z]);
|
||||
}
|
||||
|
||||
|
||||
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]);
|
||||
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortZ[0][0]);
|
||||
|
||||
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
@@ -391,7 +391,7 @@ void cBioGenDistortedVoronoi::Distort(int a_BlockX, int a_BlockZ, int & a_Distor
|
||||
double NoiseZ = m_Noise.CubicNoise3D(static_cast<float>(a_BlockX / m_CellSize), static_cast<float>(a_BlockZ / m_CellSize), 4000);
|
||||
NoiseZ += 0.5 * m_Noise.CubicNoise3D(2 * static_cast<float>(a_BlockX / m_CellSize), 2 * static_cast<float>(a_BlockZ / m_CellSize), 5000);
|
||||
NoiseZ += 0.08 * m_Noise.CubicNoise3D(16 * static_cast<float>(a_BlockX / m_CellSize), 16 * static_cast<float>(a_BlockZ / m_CellSize), 6000);
|
||||
|
||||
|
||||
a_DistortedX = a_BlockX + static_cast<int>(m_CellSize * 0.5 * NoiseX);
|
||||
a_DistortedZ = a_BlockZ + static_cast<int>(m_CellSize * 0.5 * NoiseZ);
|
||||
}
|
||||
@@ -450,7 +450,7 @@ void cBioGenMultiStepMap::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::Biome
|
||||
void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
|
||||
{
|
||||
// Distorted Voronoi over 3 biomes, with mushroom having only a special occurence.
|
||||
|
||||
|
||||
// Prepare a distortion lookup table, by distorting a 5x5 area and using that as 1:4 zoom (linear interpolate):
|
||||
int BaseZ = cChunkDef::Width * a_ChunkZ;
|
||||
int BaseX = cChunkDef::Width * a_ChunkX;
|
||||
@@ -463,7 +463,7 @@ void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cC
|
||||
}
|
||||
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]);
|
||||
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortZ[0][0]);
|
||||
|
||||
|
||||
// Prepare a 9x9 area of neighboring cell seeds
|
||||
// (assuming that 7x7 cell area is larger than a chunk being generated)
|
||||
const int NEIGHBORHOOD_SIZE = 4; // How many seeds in each direction to check
|
||||
@@ -487,7 +487,7 @@ void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cC
|
||||
SeedV[xc][zc] = (((m_Noise6.IntNoise3DInt(RealCellX, RealCellX - RealCellZ + 1000, RealCellZ) / 11) % 256) > 90) ? biOcean : (biInvalidBiome);
|
||||
} // for z
|
||||
} // for x
|
||||
|
||||
|
||||
for (int xc = 1; xc < 2 * NEIGHBORHOOD_SIZE; xc++) for (int zc = 1; zc < 2 * NEIGHBORHOOD_SIZE; zc++)
|
||||
{
|
||||
if (
|
||||
@@ -505,7 +505,7 @@ void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cC
|
||||
SeedV[xc][zc] = biMushroomIsland;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For each column find the nearest distorted cell and use its value as the biome:
|
||||
int MushroomOceanThreshold = m_OceanCellSize * m_OceanCellSize * m_MushroomIslandSize / 1024;
|
||||
int MushroomShoreThreshold = m_OceanCellSize * m_OceanCellSize * m_MushroomIslandSize / 2048;
|
||||
@@ -562,13 +562,13 @@ void cBioGenMultiStepMap::AddRivers(int a_ChunkX, int a_ChunkZ, cChunkDef::Biome
|
||||
// Biome already set, skip this column
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
float NoiseCoordX = static_cast<float>(a_ChunkX * cChunkDef::Width + x) / m_RiverCellSize;
|
||||
|
||||
|
||||
double Noise = m_Noise1.CubicNoise2D( NoiseCoordX, NoiseCoordZ);
|
||||
Noise += 0.5 * m_Noise3.CubicNoise2D(2 * NoiseCoordX, 2 * NoiseCoordZ);
|
||||
Noise += 0.1 * m_Noise5.CubicNoise2D(8 * NoiseCoordX, 8 * NoiseCoordZ);
|
||||
|
||||
|
||||
if ((Noise > 0) && (Noise < m_RiverWidthThreshold))
|
||||
{
|
||||
cChunkDef::SetBiome(a_BiomeMap, x, z, biRiver);
|
||||
@@ -586,7 +586,7 @@ void cBioGenMultiStepMap::ApplyTemperatureHumidity(int a_ChunkX, int a_ChunkZ, c
|
||||
IntMap TemperatureMap;
|
||||
IntMap HumidityMap;
|
||||
BuildTemperatureHumidityMaps(a_ChunkX, a_ChunkZ, TemperatureMap, HumidityMap);
|
||||
|
||||
|
||||
FreezeWaterBiomes(a_BiomeMap, TemperatureMap);
|
||||
DecideLandBiomes(a_BiomeMap, TemperatureMap, HumidityMap);
|
||||
}
|
||||
@@ -603,7 +603,7 @@ void cBioGenMultiStepMap::Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX
|
||||
double NoiseZ = m_Noise6.CubicNoise2D( static_cast<float>(a_BlockX / a_CellSize), static_cast<float>(a_BlockZ / a_CellSize));
|
||||
NoiseZ += 0.5 * m_Noise5.CubicNoise2D(2 * static_cast<float>(a_BlockX / a_CellSize), 2 * static_cast<float>(a_BlockZ / a_CellSize));
|
||||
NoiseZ += 0.1 * m_Noise4.CubicNoise2D(16 * static_cast<float>(a_BlockX / a_CellSize), 16 * static_cast<float>(a_BlockZ / a_CellSize));
|
||||
|
||||
|
||||
a_DistortedX = a_BlockX + static_cast<int>(a_CellSize * 0.5 * NoiseX);
|
||||
a_DistortedZ = a_BlockZ + static_cast<int>(a_CellSize * 0.5 * NoiseZ);
|
||||
}
|
||||
@@ -623,7 +623,7 @@ void cBioGenMultiStepMap::BuildTemperatureHumidityMaps(int a_ChunkX, int a_Chunk
|
||||
for (int x = 0; x < 17; x += 8)
|
||||
{
|
||||
float NoiseCoordX = static_cast<float>(a_ChunkX * cChunkDef::Width + x) / m_LandBiomesSize;
|
||||
|
||||
|
||||
double NoiseT = m_Noise1.CubicNoise2D( NoiseCoordX, NoiseCoordZ);
|
||||
NoiseT += 0.5 * m_Noise2.CubicNoise2D(2 * NoiseCoordX, 2 * NoiseCoordZ);
|
||||
NoiseT += 0.1 * m_Noise3.CubicNoise2D(8 * NoiseCoordX, 8 * NoiseCoordZ);
|
||||
@@ -637,7 +637,7 @@ void cBioGenMultiStepMap::BuildTemperatureHumidityMaps(int a_ChunkX, int a_Chunk
|
||||
} // for z
|
||||
LinearUpscale2DArrayInPlace<17, 17, 8, 8>(TemperatureMap);
|
||||
LinearUpscale2DArrayInPlace<17, 17, 8, 8>(HumidityMap);
|
||||
|
||||
|
||||
// Re-map into integral values in [0 .. 255] range:
|
||||
for (size_t idx = 0; idx < ARRAYCOUNT(a_TemperatureMap); idx++)
|
||||
{
|
||||
@@ -756,7 +756,7 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
|
||||
{
|
||||
int BaseZ = cChunkDef::Width * a_ChunkZ;
|
||||
int BaseX = cChunkDef::Width * a_ChunkX;
|
||||
|
||||
|
||||
// Distortions for linear interpolation:
|
||||
int DistortX[cChunkDef::Width + 1][cChunkDef::Width + 1];
|
||||
int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1];
|
||||
@@ -770,14 +770,14 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
|
||||
double NoiseZ = m_AmpZ1 * m_Noise4.CubicNoise2D(BlockX * m_FreqZ1, BlockZ * m_FreqZ1);
|
||||
NoiseZ += m_AmpZ2 * m_Noise5.CubicNoise2D(BlockX * m_FreqZ2, BlockZ * m_FreqZ2);
|
||||
NoiseZ += m_AmpZ3 * m_Noise6.CubicNoise2D(BlockX * m_FreqZ3, BlockZ * m_FreqZ3);
|
||||
|
||||
|
||||
DistortX[4 * x][4 * z] = static_cast<int>(BlockX + NoiseX);
|
||||
DistortZ[4 * x][4 * z] = static_cast<int>(BlockZ + NoiseZ);
|
||||
}
|
||||
|
||||
|
||||
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]);
|
||||
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortZ[0][0]);
|
||||
|
||||
|
||||
// Apply distortion to each block coord, then query the voronoi maps for biome group and biome index and choose biome based on that:
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
@@ -804,7 +804,7 @@ EMCSBiome cBioGenTwoLevel::SelectBiome(int a_BiomeGroup, size_t a_BiomeIdx, int
|
||||
EMCSBiome InnerBiome;
|
||||
EMCSBiome OuterBiome;
|
||||
} ;
|
||||
|
||||
|
||||
static BiomeLevels bgOcean[] =
|
||||
{
|
||||
{ biOcean, biOcean, },
|
||||
@@ -941,7 +941,7 @@ public:
|
||||
cBioGenGrown(int a_Seed)
|
||||
{
|
||||
auto FinalRivers =
|
||||
|
||||
|
||||
std::make_shared<cIntGenChoice<2, 7>>(a_Seed + 12)
|
||||
| MakeIntGen<cIntGenZoom <10>>(a_Seed + 11)
|
||||
| MakeIntGen<cIntGenSmooth<8>>(a_Seed + 6)
|
||||
|
||||
@@ -27,7 +27,7 @@ class cBioGenConstant :
|
||||
{
|
||||
public:
|
||||
cBioGenConstant(void) : m_Biome(biPlains) {}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
EMCSBiome m_Biome;
|
||||
@@ -46,32 +46,32 @@ class cBioGenCache :
|
||||
public cBiomeGen
|
||||
{
|
||||
typedef cBiomeGen super;
|
||||
|
||||
|
||||
public:
|
||||
cBioGenCache(cBiomeGenPtr a_BioGenToCache, size_t a_CacheSize);
|
||||
virtual ~cBioGenCache();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
cBiomeGenPtr m_BioGenToCache;
|
||||
|
||||
|
||||
struct sCacheData
|
||||
{
|
||||
int m_ChunkX;
|
||||
int m_ChunkZ;
|
||||
cChunkDef::BiomeMap m_BiomeMap;
|
||||
} ;
|
||||
|
||||
|
||||
// To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data
|
||||
size_t m_CacheSize;
|
||||
size_t * m_CacheOrder; // MRU-ized order, indices into m_CacheData array
|
||||
sCacheData * m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used
|
||||
|
||||
|
||||
// Cache statistics
|
||||
size_t m_NumHits;
|
||||
size_t m_NumMisses;
|
||||
size_t m_TotalChain; // Number of cache items walked to get to a hit (only added for hits)
|
||||
|
||||
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
||||
} ;
|
||||
@@ -117,13 +117,13 @@ class cBiomeGenList :
|
||||
public cBiomeGen
|
||||
{
|
||||
typedef cBiomeGen super;
|
||||
|
||||
|
||||
protected:
|
||||
// List of biomes that the generator is allowed to generate:
|
||||
typedef std::vector<EMCSBiome> EMCSBiomes;
|
||||
EMCSBiomes m_Biomes;
|
||||
int m_BiomesCount; // Pulled out of m_Biomes for faster access
|
||||
|
||||
|
||||
/** Parses the INI file setting string into m_Biomes. */
|
||||
void InitializeBiomes(const AString & a_Biomes);
|
||||
} ;
|
||||
@@ -136,10 +136,10 @@ class cBioGenCheckerboard :
|
||||
public cBiomeGenList
|
||||
{
|
||||
typedef cBiomeGenList super;
|
||||
|
||||
|
||||
protected:
|
||||
int m_BiomeSize;
|
||||
|
||||
|
||||
// cBiomeGen overrides:
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
||||
@@ -153,20 +153,20 @@ class cBioGenVoronoi :
|
||||
public cBiomeGenList
|
||||
{
|
||||
typedef cBiomeGenList super;
|
||||
|
||||
|
||||
public:
|
||||
cBioGenVoronoi(int a_Seed) :
|
||||
m_Voronoi(a_Seed)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
cVoronoiMap m_Voronoi;
|
||||
|
||||
|
||||
// cBiomeGen overrides:
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
||||
|
||||
|
||||
EMCSBiome VoronoiBiome(int a_BlockX, int a_BlockZ);
|
||||
} ;
|
||||
|
||||
@@ -178,7 +178,7 @@ class cBioGenDistortedVoronoi :
|
||||
public cBiomeGenList
|
||||
{
|
||||
typedef cBiomeGenList super;
|
||||
|
||||
|
||||
public:
|
||||
cBioGenDistortedVoronoi(int a_Seed) :
|
||||
m_Noise(a_Seed),
|
||||
@@ -190,17 +190,17 @@ public:
|
||||
protected:
|
||||
/** Noise used for the distortion */
|
||||
cNoise m_Noise;
|
||||
|
||||
|
||||
/** The underlying Voronoi map of the biomes */
|
||||
cVoronoiMap m_Voronoi;
|
||||
|
||||
|
||||
/** Size of the Voronoi cells, also used for distortion amplitude */
|
||||
int m_CellSize;
|
||||
|
||||
|
||||
// cBiomeGen overrides:
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
||||
|
||||
|
||||
/** Distorts the coords using a Perlin-like noise */
|
||||
void Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX, int & a_DistortedZ);
|
||||
} ;
|
||||
@@ -213,10 +213,10 @@ class cBioGenMultiStepMap :
|
||||
public cBiomeGen
|
||||
{
|
||||
typedef cBiomeGen super;
|
||||
|
||||
|
||||
public:
|
||||
cBioGenMultiStepMap(int a_Seed);
|
||||
|
||||
|
||||
protected:
|
||||
// Noises used for composing the perlin-noise:
|
||||
cNoise m_Noise1;
|
||||
@@ -225,42 +225,42 @@ protected:
|
||||
cNoise m_Noise4;
|
||||
cNoise m_Noise5;
|
||||
cNoise m_Noise6;
|
||||
|
||||
|
||||
int m_Seed;
|
||||
int m_OceanCellSize;
|
||||
int m_MushroomIslandSize;
|
||||
int m_RiverCellSize;
|
||||
double m_RiverWidthThreshold;
|
||||
float m_LandBiomesSize;
|
||||
|
||||
|
||||
typedef int IntMap[17 * 17]; // x + 17 * z, expected trimmed into [0..255] range
|
||||
typedef double DblMap[17 * 17]; // x + 17 * z, expected trimmed into [0..1] range
|
||||
|
||||
|
||||
// cBiomeGen overrides:
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
||||
|
||||
|
||||
/** Step 1: Decides between ocean, land and mushroom, using a DistVoronoi with special conditions and post-processing for mushroom islands
|
||||
Sets biomes to biOcean, -1 (i.e. land), biMushroomIsland or biMushroomShore. */
|
||||
void DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap);
|
||||
|
||||
|
||||
/** Step 2: Add rivers to the land
|
||||
Flips some "-1" biomes into biRiver. */
|
||||
void AddRivers(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap);
|
||||
|
||||
|
||||
/** Step 3: Decide land biomes using a temperature / humidity map; freeze ocean / river in low temperatures.
|
||||
Flips all remaining "-1" biomes into land biomes. Also flips some biOcean and biRiver into biFrozenOcean, biFrozenRiver, based on temp map. */
|
||||
void ApplyTemperatureHumidity(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap);
|
||||
|
||||
|
||||
/** Distorts the coords using a Perlin-like noise, with a specified cell-size */
|
||||
void Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX, int & a_DistortedZ, int a_CellSize);
|
||||
|
||||
|
||||
/** Builds two Perlin-noise maps, one for temperature, the other for humidity. Trims both into [0..255] range */
|
||||
void BuildTemperatureHumidityMaps(int a_ChunkX, int a_ChunkZ, IntMap & a_TemperatureMap, IntMap & a_HumidityMap);
|
||||
|
||||
|
||||
/** Flips all remaining "-1" biomes into land biomes using the two maps */
|
||||
void DecideLandBiomes(cChunkDef::BiomeMap & a_BiomeMap, const IntMap & a_TemperatureMap, const IntMap & a_HumidityMap);
|
||||
|
||||
|
||||
/** Flips biOcean and biRiver into biFrozenOcean and biFrozenRiver if the temperature is too low */
|
||||
void FreezeWaterBiomes(cChunkDef::BiomeMap & a_BiomeMap, const IntMap & a_TemperatureMap);
|
||||
} ;
|
||||
@@ -273,17 +273,17 @@ class cBioGenTwoLevel :
|
||||
public cBiomeGen
|
||||
{
|
||||
typedef cBiomeGen super;
|
||||
|
||||
|
||||
public:
|
||||
cBioGenTwoLevel(int a_Seed);
|
||||
|
||||
|
||||
protected:
|
||||
/** The Voronoi map that decides the groups of biomes */
|
||||
cVoronoiMap m_VoronoiLarge;
|
||||
|
||||
|
||||
/** The Voronoi map that decides biomes inside individual biome groups */
|
||||
cVoronoiMap m_VoronoiSmall;
|
||||
|
||||
|
||||
// The noises used for the distortion:
|
||||
cNoise m_Noise1;
|
||||
cNoise m_Noise2;
|
||||
|
||||
@@ -23,11 +23,11 @@ class cStructGenMarbleCaves :
|
||||
{
|
||||
public:
|
||||
cStructGenMarbleCaves(int a_Seed) : m_Seed(a_Seed) {}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_Seed;
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
} ;
|
||||
@@ -47,13 +47,13 @@ public:
|
||||
m_Threshold(a_Threshold)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
cNoise m_Noise1;
|
||||
cNoise m_Noise2;
|
||||
int m_Seed;
|
||||
float m_Threshold;
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
} ;
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
m_Grid(a_Grid)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
class cCaveSystem; // fwd: Caves.cpp
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ void cChunkDesc::GetShapeFromHeight(Shape & a_Shape) const
|
||||
{
|
||||
a_Shape[y + x * 256 + z * 16 * 256] = 1;
|
||||
}
|
||||
|
||||
|
||||
for (int y = height + 1; y < cChunkDef::Height; y++)
|
||||
{
|
||||
a_Shape[y + x * 256 + z * 16 * 256] = 0;
|
||||
@@ -590,7 +590,7 @@ cBlockEntity * cChunkDesc::GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ)
|
||||
return *itr;
|
||||
}
|
||||
} // for itr - m_BlockEntities[]
|
||||
|
||||
|
||||
// The block entity is not created yet, try to create it and add to list:
|
||||
cBlockEntity * be = cBlockEntity::CreateByBlockType(GetBlockType(a_RelX, a_RelY, a_RelZ), GetBlockMeta(a_RelX, a_RelY, a_RelZ), AbsX, a_RelY, AbsZ);
|
||||
if (be == nullptr)
|
||||
|
||||
@@ -35,28 +35,28 @@ public:
|
||||
1 = solid
|
||||
Indexed as [y + 256 * x + 256 * 16 * z]. */
|
||||
typedef Byte Shape[256 * 16 * 16];
|
||||
|
||||
|
||||
/** Uncompressed block metas, 1 meta per byte */
|
||||
typedef NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks];
|
||||
|
||||
|
||||
|
||||
cChunkDesc(int a_ChunkX, int a_ChunkZ);
|
||||
~cChunkDesc();
|
||||
|
||||
void SetChunkCoords(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
||||
int GetChunkX(void) const { return m_ChunkX; }
|
||||
int GetChunkZ(void) const { return m_ChunkZ; }
|
||||
|
||||
|
||||
void FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
void SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
|
||||
|
||||
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType);
|
||||
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
|
||||
void SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta);
|
||||
NIBBLETYPE GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
|
||||
/** Returns the minimum height value in the heightmap. */
|
||||
HEIGHTTYPE GetMinHeight(void) const;
|
||||
|
||||
|
||||
/** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */
|
||||
void FillRelCuboid(
|
||||
int a_MinX, int a_MaxX,
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
int a_MinZ, int a_MaxZ,
|
||||
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
|
||||
);
|
||||
|
||||
|
||||
/** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */
|
||||
void FillRelCuboid(const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||
{
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
a_BlockType, a_BlockMeta
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */
|
||||
void ReplaceRelCuboid(
|
||||
int a_MinX, int a_MaxX,
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta,
|
||||
BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta
|
||||
);
|
||||
|
||||
|
||||
/** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */
|
||||
void ReplaceRelCuboid(
|
||||
const cCuboid & a_RelCuboid,
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
int a_MinZ, int a_MaxZ,
|
||||
BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta
|
||||
);
|
||||
|
||||
|
||||
/** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */
|
||||
void FloorRelCuboid(
|
||||
const cCuboid & a_RelCuboid,
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
a_DstType, a_DstMeta
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */
|
||||
void RandomFillRelCuboid(
|
||||
int a_MinX, int a_MaxX,
|
||||
@@ -175,7 +175,7 @@ public:
|
||||
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
|
||||
int a_RandomSeed, int a_ChanceOutOf10k
|
||||
);
|
||||
|
||||
|
||||
/** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */
|
||||
void RandomFillRelCuboid(
|
||||
const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
|
||||
@@ -190,18 +190,18 @@ public:
|
||||
a_RandomSeed, a_ChanceOutOf10k
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** Returns the block entity at the specified coords.
|
||||
If there is no block entity at those coords, tries to create one, based on the block type
|
||||
If the blocktype doesn't support a block entity, returns nullptr. */
|
||||
cBlockEntity * GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
|
||||
/** Updates the heightmap to match the current contents.
|
||||
Useful for plugins when writing custom block areas into the chunk */
|
||||
void UpdateHeightmap(void);
|
||||
|
||||
|
||||
// tolua_end
|
||||
|
||||
|
||||
// Accessors used by cChunkGenerator::Generator descendants:
|
||||
inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; }
|
||||
inline cChunkDef::BlockTypes & GetBlockTypes (void) { return *(reinterpret_cast<cChunkDef::BlockTypes *>(m_BlockArea.GetBlockTypes())); }
|
||||
@@ -211,19 +211,19 @@ public:
|
||||
inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; }
|
||||
inline cEntityList & GetEntities (void) { return m_Entities; }
|
||||
inline cBlockEntityList & GetBlockEntities (void) { return m_BlockEntities; }
|
||||
|
||||
|
||||
/** Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) */
|
||||
void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas);
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
/** Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column */
|
||||
void VerifyHeightmap(void);
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
private:
|
||||
int m_ChunkX;
|
||||
int m_ChunkZ;
|
||||
|
||||
|
||||
cChunkDef::BiomeMap m_BiomeMap;
|
||||
cBlockArea m_BlockArea;
|
||||
cChunkDef::HeightMap m_HeightMap;
|
||||
|
||||
@@ -64,7 +64,7 @@ bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a
|
||||
LOGINFO("Chosen a new random seed for world: %d", m_Seed);
|
||||
a_IniFile.SetValueI("Seed", "Seed", m_Seed);
|
||||
}
|
||||
|
||||
|
||||
// Get the generator engine based on the INI file settings:
|
||||
AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable");
|
||||
if (NoCaseCompare(GeneratorName, "Noise3D") == 0)
|
||||
|
||||
@@ -37,7 +37,7 @@ class cChunkGenerator :
|
||||
cIsThread
|
||||
{
|
||||
typedef cIsThread super;
|
||||
|
||||
|
||||
public:
|
||||
/** The interface that a class has to implement to become a generator */
|
||||
class cGenerator
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
|
||||
/** Called to initialize the generator on server startup. */
|
||||
virtual void Initialize(cIniFile & a_IniFile);
|
||||
|
||||
|
||||
/** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */
|
||||
virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0;
|
||||
|
||||
@@ -57,47 +57,47 @@ public:
|
||||
|
||||
/** Called in a separate thread to do the actual chunk generation. Generator should generate into a_ChunkDesc. */
|
||||
virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
cChunkGenerator & m_ChunkGenerator;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
/** The interface through which the plugins are called for their OnChunkGenerating / OnChunkGenerated hooks. */
|
||||
class cPluginInterface
|
||||
{
|
||||
public:
|
||||
// Force a virtual destructor
|
||||
virtual ~cPluginInterface() {}
|
||||
|
||||
|
||||
/** Called when the chunk is about to be generated.
|
||||
The generator may be partly or fully overriden by the implementation. */
|
||||
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) = 0;
|
||||
|
||||
|
||||
/** Called after the chunk is generated, before it is handed to the chunk sink.
|
||||
a_ChunkDesc contains the generated chunk data. Implementation may modify this data. */
|
||||
virtual void CallHookChunkGenerated(cChunkDesc & a_ChunkDesc) = 0;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
/** The interface through which the generated chunks are handed to the cWorld or whoever created us. */
|
||||
class cChunkSink
|
||||
{
|
||||
public:
|
||||
// Force a virtual destructor
|
||||
virtual ~cChunkSink() {}
|
||||
|
||||
|
||||
/** Called after the chunk has been generated
|
||||
The interface may store the chunk, send it over network, whatever.
|
||||
The chunk is not expected to be modified, but the generator will survive if the implementation
|
||||
changes the data within. All changes are ignored, though. */
|
||||
virtual void OnChunkGenerated(cChunkDesc & a_ChunkDesc) = 0;
|
||||
|
||||
|
||||
/** Called just before the chunk generation is started,
|
||||
to verify that it hasn't been generated in the meantime.
|
||||
If this callback returns true, the chunk is not generated. */
|
||||
virtual bool IsChunkValid(int a_ChunkX, int a_ChunkZ) = 0;
|
||||
|
||||
|
||||
/** Called when the generator is overloaded to skip chunks that are no longer needed.
|
||||
If this callback returns false, the chunk is not generated. */
|
||||
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
Currently used only in Debug-mode asserts. */
|
||||
virtual bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) = 0;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
cChunkGenerator (void);
|
||||
~cChunkGenerator();
|
||||
@@ -120,22 +120,22 @@ public:
|
||||
It is legal to set the callback to nullptr, no callback is called then.
|
||||
If the generator becomes overloaded and skips this chunk, the callback is still called. */
|
||||
void QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate, cChunkCoordCallback * a_Callback = nullptr);
|
||||
|
||||
|
||||
/** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */
|
||||
void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap);
|
||||
|
||||
|
||||
void WaitForQueueEmpty(void);
|
||||
|
||||
|
||||
int GetQueueLength(void);
|
||||
|
||||
|
||||
int GetSeed(void) const { return m_Seed; }
|
||||
|
||||
|
||||
/** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome */
|
||||
EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ);
|
||||
|
||||
/** Reads a block type from the ini file; returns the blocktype on success, emits a warning and returns a_Default's representation on failure. */
|
||||
static BLOCKTYPE GetIniBlock(cIniFile & a_IniFile, const AString & a_SectionName, const AString & a_ValueName, const AString & a_Default);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
struct cQueueItem
|
||||
@@ -167,16 +167,16 @@ private:
|
||||
|
||||
/** Set when an item is removed from the queue. */
|
||||
cEvent m_evtRemoved;
|
||||
|
||||
|
||||
/** The actual generator engine used to generate chunks. */
|
||||
cGenerator * m_Generator;
|
||||
|
||||
|
||||
/** The plugin interface that may modify the generated chunks */
|
||||
cPluginInterface * m_PluginInterface;
|
||||
|
||||
|
||||
/** The destination where the generated chunks are sent */
|
||||
cChunkSink * m_ChunkSink;
|
||||
|
||||
|
||||
|
||||
// cIsThread override:
|
||||
virtual void Execute(void) override;
|
||||
|
||||
@@ -92,7 +92,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunk
|
||||
E_BLOCK_NETHER_BRICK,
|
||||
E_BLOCK_BEDROCK,
|
||||
} ;
|
||||
|
||||
|
||||
a_ChunkDesc.SetHeightFromShape(a_Shape);
|
||||
a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
|
||||
|
||||
@@ -153,7 +153,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc
|
||||
static int PatternLength = ARRAYCOUNT(PatternGround);
|
||||
ASSERT(ARRAYCOUNT(PatternGround) == ARRAYCOUNT(PatternBeach));
|
||||
ASSERT(ARRAYCOUNT(PatternGround) == ARRAYCOUNT(PatternOcean));
|
||||
|
||||
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
@@ -172,19 +172,19 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc
|
||||
{
|
||||
Pattern = PatternOcean;
|
||||
}
|
||||
|
||||
|
||||
// Fill water from sealevel down to height (if any):
|
||||
for (int y = m_SeaLevel; y >= Height; --y)
|
||||
{
|
||||
a_ChunkDesc.SetBlockType(x, y, z, m_BlockSea);
|
||||
}
|
||||
|
||||
|
||||
// Fill from height till the bottom:
|
||||
for (int y = Height; y >= 1; y--)
|
||||
{
|
||||
a_ChunkDesc.SetBlockType(x, y, z, (Height - y < PatternLength) ? Pattern[Height - y] : m_BlockBottom);
|
||||
}
|
||||
|
||||
|
||||
// The last layer is always bedrock:
|
||||
a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK);
|
||||
} // for x
|
||||
@@ -229,21 +229,21 @@ cCompoGenNether::cCompoGenNether(int a_Seed) :
|
||||
void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape)
|
||||
{
|
||||
HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight();
|
||||
|
||||
|
||||
const int SEGMENT_HEIGHT = 8;
|
||||
const int INTERPOL_X = 16; // Must be a divisor of 16
|
||||
const int INTERPOL_Z = 16; // Must be a divisor of 16
|
||||
// Interpolate the chunk in 16 * SEGMENT_HEIGHT * 16 "segments", each SEGMENT_HEIGHT blocks high and each linearly interpolated separately.
|
||||
// Have two buffers, one for the lowest floor and one for the highest floor, so that Y-interpolation can be done between them
|
||||
// Then swap the buffers and use the previously-top one as the current-bottom, without recalculating it.
|
||||
|
||||
|
||||
int FloorBuf1[17 * 17];
|
||||
int FloorBuf2[17 * 17];
|
||||
int * FloorHi = FloorBuf1;
|
||||
int * FloorLo = FloorBuf2;
|
||||
int BaseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||
int BaseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||
|
||||
|
||||
// Interpolate the lowest floor:
|
||||
for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
|
||||
{
|
||||
@@ -259,7 +259,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc:
|
||||
//*/
|
||||
} // for x, z - FloorLo[]
|
||||
LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo);
|
||||
|
||||
|
||||
// Interpolate segments:
|
||||
for (int Segment = 0; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
|
||||
{
|
||||
@@ -278,7 +278,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc:
|
||||
//*/
|
||||
} // for x, z - FloorLo[]
|
||||
LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi);
|
||||
|
||||
|
||||
// Interpolate between FloorLo and FloorHi:
|
||||
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
||||
{
|
||||
@@ -294,11 +294,11 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Swap the floors:
|
||||
std::swap(FloorLo, FloorHi);
|
||||
}
|
||||
|
||||
|
||||
// Bedrock at the bottom and at the top:
|
||||
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
||||
{
|
||||
@@ -380,10 +380,10 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::
|
||||
LOGD("CompoGenCache: Avg cache chain length: %.2f", static_cast<float>(m_TotalChain) / m_NumHits);
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
|
||||
|
||||
for (int i = 0; i < m_CacheSize; i++)
|
||||
{
|
||||
if (
|
||||
@@ -395,28 +395,28 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::
|
||||
}
|
||||
// Found it in the cache
|
||||
int Idx = m_CacheOrder[i];
|
||||
|
||||
|
||||
// Move to front:
|
||||
for (int j = i; j > 0; j--)
|
||||
{
|
||||
m_CacheOrder[j] = m_CacheOrder[j - 1];
|
||||
}
|
||||
m_CacheOrder[0] = Idx;
|
||||
|
||||
|
||||
// Use the cached data:
|
||||
memcpy(a_ChunkDesc.GetBlockTypes(), m_CacheData[Idx].m_BlockTypes, sizeof(a_ChunkDesc.GetBlockTypes()));
|
||||
memcpy(a_ChunkDesc.GetBlockMetasUncompressed(), m_CacheData[Idx].m_BlockMetas, sizeof(a_ChunkDesc.GetBlockMetasUncompressed()));
|
||||
memcpy(a_ChunkDesc.GetHeightMap(), m_CacheData[Idx].m_HeightMap, sizeof(a_ChunkDesc.GetHeightMap()));
|
||||
|
||||
|
||||
m_NumHits++;
|
||||
m_TotalChain += i;
|
||||
return;
|
||||
} // for i - cache
|
||||
|
||||
|
||||
// Not in the cache:
|
||||
m_NumMisses++;
|
||||
m_Underlying->ComposeTerrain(a_ChunkDesc, a_Shape);
|
||||
|
||||
|
||||
// Insert it as the first item in the MRU order:
|
||||
int Idx = m_CacheOrder[m_CacheSize - 1];
|
||||
for (int i = m_CacheSize - 1; i > 0; i--)
|
||||
|
||||
@@ -31,12 +31,12 @@ public:
|
||||
m_BlockType(E_BLOCK_STONE),
|
||||
m_IsBedrocked(true)
|
||||
{}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
BLOCKTYPE m_BlockType;
|
||||
bool m_IsBedrocked;
|
||||
|
||||
|
||||
// cTerrainCompositionGen overrides:
|
||||
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
|
||||
@@ -51,9 +51,9 @@ class cCompoGenDebugBiomes :
|
||||
{
|
||||
public:
|
||||
cCompoGenDebugBiomes(void) {}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
// cTerrainCompositionGen overrides:
|
||||
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override;
|
||||
} ;
|
||||
@@ -67,7 +67,7 @@ class cCompoGenClassic :
|
||||
{
|
||||
public:
|
||||
cCompoGenClassic(void);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_SeaLevel;
|
||||
@@ -79,7 +79,7 @@ protected:
|
||||
BLOCKTYPE m_BlockBeach;
|
||||
BLOCKTYPE m_BlockBeachBottom;
|
||||
BLOCKTYPE m_BlockSea;
|
||||
|
||||
|
||||
// cTerrainCompositionGen overrides:
|
||||
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
|
||||
@@ -94,13 +94,13 @@ class cCompoGenNether :
|
||||
{
|
||||
public:
|
||||
cCompoGenNether(int a_Seed);
|
||||
|
||||
|
||||
protected:
|
||||
cNoise m_Noise1;
|
||||
cNoise m_Noise2;
|
||||
|
||||
|
||||
double m_MaxThreshold;
|
||||
|
||||
|
||||
// cTerrainCompositionGen overrides:
|
||||
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
|
||||
@@ -117,15 +117,15 @@ class cCompoGenCache :
|
||||
public:
|
||||
cCompoGenCache(cTerrainCompositionGenPtr a_Underlying, int a_CacheSize); // Doesn't take ownership of a_Underlying
|
||||
~cCompoGenCache();
|
||||
|
||||
|
||||
// cTerrainCompositionGen override:
|
||||
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
cTerrainCompositionGenPtr m_Underlying;
|
||||
|
||||
|
||||
struct sCacheData
|
||||
{
|
||||
int m_ChunkX;
|
||||
@@ -134,12 +134,12 @@ protected:
|
||||
cChunkDesc::BlockNibbleBytes m_BlockMetas; // The metas are uncompressed, 1 meta per byte
|
||||
cChunkDef::HeightMap m_HeightMap;
|
||||
} ;
|
||||
|
||||
|
||||
// To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data
|
||||
int m_CacheSize;
|
||||
int * m_CacheOrder; // MRU-ized order, indices into m_CacheData array
|
||||
sCacheData * m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used
|
||||
|
||||
|
||||
// Cache statistics
|
||||
int m_NumHits;
|
||||
int m_NumMisses;
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
{
|
||||
m_Pattern[i] = a_TopBlocks[i];
|
||||
}
|
||||
|
||||
|
||||
// Fill the rest with stone:
|
||||
static BlockInfo Stone = {E_BLOCK_STONE, 0};
|
||||
for (int i = static_cast<int>(a_Count); i < cChunkDef::Height; i++)
|
||||
@@ -47,9 +47,9 @@ public:
|
||||
m_Pattern[i] = Stone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const BlockInfo * Get(void) const { return m_Pattern; }
|
||||
|
||||
|
||||
protected:
|
||||
BlockInfo m_Pattern[cChunkDef::Height];
|
||||
} ;
|
||||
@@ -192,14 +192,14 @@ public:
|
||||
{
|
||||
initMesaPattern(a_Seed);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
/** The block height at which water is generated instead of air. */
|
||||
HEIGHTTYPE m_SeaLevel;
|
||||
|
||||
/** The pattern used for mesa biomes. Initialized by seed on generator creation. */
|
||||
cPattern::BlockInfo m_MesaPattern[2 * cChunkDef::Height];
|
||||
|
||||
|
||||
/** Noise used for selecting between dirt and sand on the ocean floor. */
|
||||
cNoise m_OceanFloorSelect;
|
||||
|
||||
@@ -226,7 +226,7 @@ protected:
|
||||
{
|
||||
m_SeaLevel = static_cast<HEIGHTTYPE>(a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Initializes the m_MesaPattern with a pattern based on the generator's seed. */
|
||||
@@ -309,7 +309,7 @@ protected:
|
||||
// Frequencies for the podzol floor selecting noise:
|
||||
const NOISE_DATATYPE FrequencyX = 8;
|
||||
const NOISE_DATATYPE FrequencyZ = 8;
|
||||
|
||||
|
||||
EMCSBiome Biome = a_ChunkDesc.GetBiome(a_RelX, a_RelZ);
|
||||
switch (Biome)
|
||||
{
|
||||
@@ -381,7 +381,7 @@ protected:
|
||||
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patSand.Get(), a_ShapeColumn);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case biMushroomIsland:
|
||||
case biMushroomShore:
|
||||
{
|
||||
@@ -426,7 +426,7 @@ protected:
|
||||
}
|
||||
} // switch (Biome)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Fills the specified column with the specified pattern; restarts the pattern when air is reached,
|
||||
@@ -445,23 +445,23 @@ protected:
|
||||
PatternIdx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// "air" or "water" part:
|
||||
// Reset the pattern index to zero, so that the pattern is repeated from the top again:
|
||||
PatternIdx = 0;
|
||||
|
||||
|
||||
if (y >= m_SeaLevel)
|
||||
{
|
||||
// "air" part, do nothing
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER);
|
||||
if (HasHadWater)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Select the ocean-floor pattern to use:
|
||||
if (a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean)
|
||||
{
|
||||
@@ -500,7 +500,7 @@ protected:
|
||||
{
|
||||
ClayFloor = Top - 1;
|
||||
}
|
||||
|
||||
|
||||
if (Top - m_SeaLevel < 5)
|
||||
{
|
||||
// Simple case: top is red sand, then hardened clay down to ClayFloor, then stone:
|
||||
@@ -516,7 +516,7 @@ protected:
|
||||
a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Difficult case: use the mesa pattern and watch for overhangs:
|
||||
int PatternIdx = cChunkDef::Height - (Top - ClayFloor); // We want the block at index ClayFloor to be pattern's 256th block (first stone)
|
||||
const cPattern::BlockInfo * Pattern = m_MesaPattern;
|
||||
@@ -536,7 +536,7 @@ protected:
|
||||
// "air" part, do nothing
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// "water" part, fill with water and choose new pattern for ocean floor, if not chosen already:
|
||||
PatternIdx = 0;
|
||||
a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER);
|
||||
@@ -544,7 +544,7 @@ protected:
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Select the ocean-floor pattern to use:
|
||||
Pattern = ChooseOceanFloorPattern(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ);
|
||||
HasHadWater = true;
|
||||
@@ -567,7 +567,7 @@ protected:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns the pattern to use for an ocean floor in the specified column.
|
||||
The returned pattern is guaranteed to be 256 blocks long. */
|
||||
const cPattern::BlockInfo * ChooseOceanFloorPattern(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ)
|
||||
|
||||
@@ -47,7 +47,7 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile
|
||||
LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
|
||||
CompoGenName = "Biomal";
|
||||
}
|
||||
|
||||
|
||||
// Compositor list is alpha-sorted
|
||||
cTerrainCompositionGenPtr res;
|
||||
if (NoCaseCompare(CompoGenName, "Biomal") == 0)
|
||||
@@ -96,10 +96,10 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile
|
||||
return CreateCompositionGen(a_IniFile, a_BiomeGen, a_ShapeGen, a_Seed);
|
||||
}
|
||||
ASSERT(res != nullptr);
|
||||
|
||||
|
||||
// Read the settings from the ini file:
|
||||
res->InitializeCompoGen(a_IniFile);
|
||||
|
||||
|
||||
return cTerrainCompositionGenPtr(res);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) :
|
||||
void cComposableGenerator::Initialize(cIniFile & a_IniFile)
|
||||
{
|
||||
super::Initialize(a_IniFile);
|
||||
|
||||
|
||||
InitBiomeGen(a_IniFile);
|
||||
InitShapeGen(a_IniFile);
|
||||
InitCompositionGen(a_IniFile);
|
||||
@@ -154,7 +154,7 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a
|
||||
{
|
||||
m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetBiomeMap());
|
||||
}
|
||||
|
||||
|
||||
cChunkDesc::Shape shape;
|
||||
if (a_ChunkDesc.IsUsingDefaultHeight())
|
||||
{
|
||||
@@ -166,7 +166,7 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a
|
||||
// Convert the heightmap in a_ChunkDesc into shape:
|
||||
a_ChunkDesc.GetShapeFromHeight(shape);
|
||||
}
|
||||
|
||||
|
||||
bool ShouldUpdateHeightmap = false;
|
||||
if (a_ChunkDesc.IsUsingDefaultComposition())
|
||||
{
|
||||
@@ -181,7 +181,7 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a
|
||||
} // for itr - m_FinishGens[]
|
||||
ShouldUpdateHeightmap = true;
|
||||
}
|
||||
|
||||
|
||||
if (ShouldUpdateHeightmap)
|
||||
{
|
||||
a_ChunkDesc.UpdateHeightmap();
|
||||
@@ -196,7 +196,7 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
|
||||
{
|
||||
bool CacheOffByDefault = false;
|
||||
m_BiomeGen = cBiomeGen::CreateBiomeGen(a_IniFile, m_ChunkGenerator.GetSeed(), CacheOffByDefault);
|
||||
|
||||
|
||||
// Add a cache, if requested:
|
||||
// The default is 16 * 128 caches, which is 2 MiB of RAM. Reasonable, for the amount of work this is saving.
|
||||
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 16);
|
||||
@@ -232,7 +232,7 @@ void cComposableGenerator::InitShapeGen(cIniFile & a_IniFile)
|
||||
{
|
||||
bool CacheOffByDefault = false;
|
||||
m_ShapeGen = cTerrainShapeGen::CreateShapeGen(a_IniFile, m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault);
|
||||
|
||||
|
||||
/*
|
||||
// TODO
|
||||
// Add a cache, if requested:
|
||||
@@ -259,7 +259,7 @@ void cComposableGenerator::InitShapeGen(cIniFile & a_IniFile)
|
||||
void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
|
||||
{
|
||||
m_CompositionGen = cTerrainCompositionGen::CreateCompositionGen(a_IniFile, m_BiomeGen, m_ShapeGen, m_ChunkGenerator.GetSeed());
|
||||
|
||||
|
||||
// Add a cache over the composition generator:
|
||||
// Even a cache of size 1 is useful due to the CompositedHeiGen cache after us doing re-composition on its misses
|
||||
int CompoGenCacheSize = a_IniFile.GetValueSetI("Generator", "CompositionGenCacheSize", 64);
|
||||
|
||||
@@ -48,10 +48,10 @@ class cBiomeGen
|
||||
{
|
||||
public:
|
||||
virtual ~cBiomeGen() {} // Force a virtual destructor in descendants
|
||||
|
||||
|
||||
/** Generates biomes for the given chunk */
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0;
|
||||
|
||||
|
||||
/** Reads parameters from the ini file, prepares generator for use. */
|
||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) {}
|
||||
|
||||
@@ -79,13 +79,13 @@ class cTerrainShapeGen
|
||||
{
|
||||
public:
|
||||
virtual ~cTerrainShapeGen() {} // Force a virtual destructor in descendants
|
||||
|
||||
|
||||
/** Generates the shape for the given chunk */
|
||||
virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) = 0;
|
||||
|
||||
|
||||
/** Reads parameters from the ini file, prepares generator for use. */
|
||||
virtual void InitializeShapeGen(cIniFile & a_IniFile) {}
|
||||
|
||||
|
||||
/** Creates the correct TerrainShapeGen descendant based on the ini file settings and the seed provided.
|
||||
a_BiomeGen is the underlying biome generator, some shape generators may depend on it providing additional biomes data around the chunk
|
||||
a_CacheOffByDefault gets set to whether the cache should be disabled by default
|
||||
@@ -142,14 +142,14 @@ class cTerrainCompositionGen
|
||||
{
|
||||
public:
|
||||
virtual ~cTerrainCompositionGen() {} // Force a virtual destructor in descendants
|
||||
|
||||
|
||||
/** Generates the chunk's composition into a_ChunkDesc, using the terrain shape provided in a_Shape.
|
||||
Is expected to fill a_ChunkDesc's heightmap with the data from a_Shape. */
|
||||
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) = 0;
|
||||
|
||||
|
||||
/** Reads parameters from the ini file, prepares generator for use. */
|
||||
virtual void InitializeCompoGen(cIniFile & a_IniFile) {}
|
||||
|
||||
|
||||
/** Creates the correct TerrainCompositionGen descendant based on the ini file settings and the seed provided.
|
||||
a_BiomeGen is the underlying biome generator, some composition generators may depend on it providing additional biomes around the chunk
|
||||
a_ShapeGen is the underlying shape generator, some composition generators may depend on it providing additional shape around the chunk
|
||||
@@ -172,7 +172,7 @@ class cFinishGen
|
||||
{
|
||||
public:
|
||||
virtual ~cFinishGen() {} // Force a virtual destructor in descendants
|
||||
|
||||
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) = 0;
|
||||
} ;
|
||||
|
||||
@@ -186,10 +186,10 @@ class cComposableGenerator :
|
||||
public cChunkGenerator::cGenerator
|
||||
{
|
||||
typedef cChunkGenerator::cGenerator super;
|
||||
|
||||
|
||||
public:
|
||||
cComposableGenerator(cChunkGenerator & a_ChunkGenerator);
|
||||
|
||||
|
||||
// cChunkGenerator::cGenerator overrides:
|
||||
virtual void Initialize(cIniFile & a_IniFile) override;
|
||||
virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
@@ -211,17 +211,17 @@ protected:
|
||||
|
||||
/** The finisher generators, in the order in which they are applied. */
|
||||
cFinishGenList m_FinishGens;
|
||||
|
||||
|
||||
|
||||
|
||||
/** Reads the BiomeGen settings from the ini and initializes m_BiomeGen accordingly */
|
||||
void InitBiomeGen(cIniFile & a_IniFile);
|
||||
|
||||
|
||||
/** Reads the ShapeGen settings from the ini and initializes m_ShapeGen accordingly */
|
||||
void InitShapeGen(cIniFile & a_IniFile);
|
||||
|
||||
|
||||
/** Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly */
|
||||
void InitCompositionGen(cIniFile & a_IniFile);
|
||||
|
||||
|
||||
/** Reads the finishers from the ini and initializes m_FinishGens accordingly */
|
||||
void InitFinishGens(cIniFile & a_IniFile);
|
||||
} ;
|
||||
|
||||
@@ -68,7 +68,7 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] =
|
||||
/* biMesa */ { 2.0f, 2.0f}, // 37
|
||||
/* biMesaPlateauF */ { 2.0f, 2.0f}, // 38
|
||||
/* biMesaPlateau */ { 2.0f, 2.0f}, // 39
|
||||
|
||||
|
||||
// biomes 40 .. 128 are unused, 89 empty placeholders here:
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 40 .. 49
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 50 .. 59
|
||||
@@ -79,7 +79,7 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] =
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 100 .. 109
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 110 .. 119
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 120 .. 128
|
||||
|
||||
|
||||
// Release 1.7 biome variants:
|
||||
/* biSunflowerPlains */ { 1.0f, 1.0f}, // 129
|
||||
/* biDesertM */ { 1.0f, 1.0f}, // 130
|
||||
@@ -87,12 +87,12 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] =
|
||||
/* biFlowerForest */ { 4.0f, 4.0f}, // 132
|
||||
/* biTaigaM */ { 3.0f, 3.0f}, // 133
|
||||
/* biSwamplandM */ { 0.0f, 0.0f}, // 134
|
||||
|
||||
|
||||
// Biomes 135 .. 139 unused, 5 empty placeholders here:
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 135 .. 139
|
||||
|
||||
/* biIcePlainsSpikes */ { 1.0f, 1.0f}, // 140
|
||||
|
||||
|
||||
// Biomes 141 .. 148 unused, 8 empty placeholders here:
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 141 .. 148
|
||||
|
||||
@@ -358,7 +358,7 @@ void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_R
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Sanity checks for biome parameters, enable them to check the biome param table in runtime (slow):
|
||||
ASSERT(m_GenParam[i].m_DistortAmpX >= 0);
|
||||
|
||||
@@ -27,7 +27,7 @@ class cDistortedHeightmap :
|
||||
{
|
||||
public:
|
||||
cDistortedHeightmap(int a_Seed, cBiomeGenPtr a_BiomeGen);
|
||||
|
||||
|
||||
protected:
|
||||
typedef cChunkDef::BiomeMap BiomeNeighbors[3][3];
|
||||
|
||||
@@ -61,10 +61,10 @@ protected:
|
||||
|
||||
/** Cache for m_UnderlyingHeiGen. */
|
||||
cHeiGenCache m_HeightGen;
|
||||
|
||||
|
||||
/** Heightmap for the current chunk, before distortion (from m_HeightGen). Used for optimization. */
|
||||
cChunkDef::HeightMap m_CurChunkHeights;
|
||||
|
||||
|
||||
// Per-biome terrain generator parameters:
|
||||
struct sGenParam
|
||||
{
|
||||
@@ -72,34 +72,34 @@ protected:
|
||||
NOISE_DATATYPE m_DistortAmpZ;
|
||||
} ;
|
||||
static const sGenParam m_GenParam[256];
|
||||
|
||||
|
||||
// Distortion amplitudes for each direction, before linear upscaling
|
||||
NOISE_DATATYPE m_DistortAmpX[DIM_X * DIM_Z];
|
||||
NOISE_DATATYPE m_DistortAmpZ[DIM_X * DIM_Z];
|
||||
|
||||
|
||||
/** True if Initialize() has been called. Used to initialize-once even with multiple init entrypoints (HeiGen / CompoGen). */
|
||||
bool m_IsInitialized;
|
||||
|
||||
|
||||
|
||||
/** Unless the LastChunk coords are equal to coords given, prepares the internal state (noise arrays, heightmap). */
|
||||
void PrepareState(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
||||
/** Generates the m_DistortedHeightmap array for the current chunk. */
|
||||
void GenerateHeightArray(void);
|
||||
|
||||
|
||||
/** Calculates the heightmap value (before distortion) at the specified (floating-point) coords. */
|
||||
int GetHeightmapAt(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Z);
|
||||
|
||||
|
||||
/** Updates m_DistortAmpX/Z[] based on m_CurChunkX and m_CurChunkZ. */
|
||||
void UpdateDistortAmps(void);
|
||||
|
||||
|
||||
/** Calculates the X and Z distortion amplitudes based on the neighbors' biomes. */
|
||||
void GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_RelX, int a_RelZ, NOISE_DATATYPE & a_DistortAmpX, NOISE_DATATYPE & a_DistortAmpZ);
|
||||
|
||||
|
||||
/** Reads the settings from the ini file. Skips reading if already initialized. */
|
||||
void Initialize(cIniFile & a_IniFile);
|
||||
|
||||
|
||||
|
||||
|
||||
// cTerrainShapeGen overrides:
|
||||
virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeShapeGen(cIniFile & a_IniFile) override;
|
||||
|
||||
@@ -22,12 +22,12 @@ class cEndGen :
|
||||
{
|
||||
public:
|
||||
cEndGen(int a_Seed);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** Seed for the noise */
|
||||
int m_Seed;
|
||||
|
||||
|
||||
/** The Perlin noise used for generating */
|
||||
cPerlinNoise m_Perlin;
|
||||
|
||||
@@ -35,16 +35,16 @@ protected:
|
||||
int m_IslandSizeX;
|
||||
int m_IslandSizeY;
|
||||
int m_IslandSizeZ;
|
||||
|
||||
|
||||
// XYZ Frequencies of the noise functions:
|
||||
NOISE_DATATYPE m_FrequencyX;
|
||||
NOISE_DATATYPE m_FrequencyY;
|
||||
NOISE_DATATYPE m_FrequencyZ;
|
||||
|
||||
|
||||
// Minimum and maximum chunk coords for chunks inside the island area. Chunks outside won't get calculated at all
|
||||
int m_MinChunkX, m_MaxChunkX;
|
||||
int m_MinChunkZ, m_MaxChunkZ;
|
||||
|
||||
|
||||
// Noise array for the last chunk (in the noise range)
|
||||
int m_LastChunkX;
|
||||
int m_LastChunkZ;
|
||||
@@ -53,10 +53,10 @@ protected:
|
||||
|
||||
/** Unless the LastChunk coords are equal to coords given, prepares the internal state (noise array) */
|
||||
void PrepareState(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
||||
/** Generates the m_NoiseArray array for the current chunk */
|
||||
void GenerateNoiseArray(void);
|
||||
|
||||
|
||||
/** Returns true if the chunk is outside of the island's dimensions */
|
||||
bool IsChunkOutsideRange(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ void cFinishGenGlowStone::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
|
||||
|
||||
// Change the number of attempts to create a vein depending on the maximum height of the chunk. A standard Nether could have 5 veins at most.
|
||||
int NumGlowStone = m_Noise.IntNoise2DInt(ChunkX, ChunkZ) % a_ChunkDesc.GetMaxHeight() / 23;
|
||||
|
||||
@@ -198,7 +198,7 @@ void cFinishGenGlowStone::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
// Generate X / Z coordinates.
|
||||
int X = Size + (m_Noise.IntNoise2DInt(i, Size) % (cChunkDef::Width - Size * 2));
|
||||
int Z = Size + (m_Noise.IntNoise2DInt(X, i) % (cChunkDef::Width - Size * 2));
|
||||
|
||||
|
||||
int Height = a_ChunkDesc.GetHeight(X, Z);
|
||||
for (int y = Height; y > Size; y--)
|
||||
{
|
||||
@@ -234,14 +234,14 @@ void cFinishGenGlowStone::TryPlaceGlowstone(cChunkDesc & a_ChunkDesc, int a_RelX
|
||||
{
|
||||
// The starting point of every glowstone string
|
||||
Vector3i StartPoint = Vector3i(a_RelX, a_RelY, a_RelZ);
|
||||
|
||||
|
||||
// Array with possible directions for a string of glowstone to go to.
|
||||
const Vector3i AvailableDirections[] =
|
||||
{
|
||||
{ -1, 0, 0 }, { 1, 0, 0 },
|
||||
{ 0, -1, 0 }, // Don't let the glowstone go up
|
||||
{ 0, 0, -1 }, { 0, 0, 1 },
|
||||
|
||||
|
||||
// Diagonal direction. Only X or Z with Y.
|
||||
// If all were changed the glowstone string looks awkward
|
||||
{ 0, -1, 1 }, { 1, -1, 0 },
|
||||
|
||||
@@ -372,7 +372,7 @@ class cFinishGenPassiveMobs :
|
||||
public cFinishGen
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -20,13 +20,13 @@ class cEmptyStructure :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
|
||||
public:
|
||||
cEmptyStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) :
|
||||
super(a_GridX, a_GridZ, a_OriginX, a_OriginZ)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
|
||||
{
|
||||
|
||||
@@ -51,11 +51,11 @@ public:
|
||||
public:
|
||||
/** The grid point for which the structure is generated. */
|
||||
int m_GridX, m_GridZ;
|
||||
|
||||
|
||||
/** The origin (the coords for which the structure is generated) */
|
||||
int m_OriginX, m_OriginZ;
|
||||
|
||||
|
||||
|
||||
|
||||
/** Creates a structure that has its origin set at the specified coords. */
|
||||
cStructure (int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) :
|
||||
m_GridX(a_GridX),
|
||||
@@ -64,20 +64,20 @@ public:
|
||||
m_OriginZ(a_OriginZ)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Force a virtual destructor in descendants:
|
||||
virtual ~cStructure() {}
|
||||
|
||||
|
||||
/** Draws self into the specified chunk */
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) = 0;
|
||||
|
||||
|
||||
/** Returns the cost of keeping this structure in the cache */
|
||||
virtual size_t GetCacheCost(void) const { return 1; }
|
||||
} ;
|
||||
typedef SharedPtr<cStructure> cStructurePtr;
|
||||
typedef std::list<cStructurePtr> cStructurePtrs;
|
||||
|
||||
|
||||
|
||||
|
||||
cGridStructGen(
|
||||
int a_Seed,
|
||||
int a_GridSizeX, int a_GridSizeZ,
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
|
||||
protected:
|
||||
/** Base seed of the world for which the generator generates chunk. */
|
||||
int m_BaseSeed;
|
||||
@@ -104,43 +104,43 @@ protected:
|
||||
/** Seed for generating grid offsets and also available for descendants.
|
||||
Calculated from m_BaseSeed by adding the SeedOffset parameter loaded from the cubeset file (if applicable); otherwise the same as m_BaseSeed. */
|
||||
int m_Seed;
|
||||
|
||||
|
||||
/** The noise used for generating grid offsets. */
|
||||
cNoise m_Noise;
|
||||
|
||||
|
||||
/** The size of each grid's cell in the X axis */
|
||||
int m_GridSizeX;
|
||||
|
||||
|
||||
/** The size of each grid's cell in the Z axis */
|
||||
int m_GridSizeZ;
|
||||
|
||||
|
||||
/** The maximum offset of the structure's origin from the grid midpoint, in X coord. */
|
||||
int m_MaxOffsetX;
|
||||
|
||||
|
||||
/** The maximum offset of the structure's origin from the grid midpoint, in Z coord. */
|
||||
int m_MaxOffsetZ;
|
||||
|
||||
|
||||
/** Maximum theoretical size of the structure in the X axis.
|
||||
This limits the structures considered for a single chunk, so the lesser the number, the better performance.
|
||||
Structures large than this may get cropped. */
|
||||
int m_MaxStructureSizeX;
|
||||
|
||||
|
||||
/** Maximum theoretical size of the structure in the Z axis.
|
||||
This limits the structures considered for a single chunk, so the lesser the number, the better performance.
|
||||
Structures large than this may get cropped. */
|
||||
int m_MaxStructureSizeZ;
|
||||
|
||||
|
||||
/** Maximum allowed sum of costs for items in the cache. Items that are over this cost are removed from the
|
||||
cache, oldest-first */
|
||||
size_t m_MaxCacheSize;
|
||||
|
||||
|
||||
/** Cache for the most recently generated structures, ordered by the recentness. */
|
||||
cStructurePtrs m_Cache;
|
||||
|
||||
|
||||
|
||||
|
||||
/** Clears everything from the cache */
|
||||
void ClearCache(void);
|
||||
|
||||
|
||||
/** Returns all structures that may intersect the given chunk.
|
||||
The structures are considered as intersecting iff their bounding box (defined by m_MaxStructureSize)
|
||||
around their gridpoint intersects the chunk. */
|
||||
|
||||
@@ -144,7 +144,7 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap
|
||||
LOGD("HeiGenCache: Avg cache chain length: %.2f", static_cast<double>(m_TotalChain) / m_NumHits);
|
||||
}
|
||||
//*/
|
||||
|
||||
|
||||
for (size_t i = 0; i < m_CacheSize; i++)
|
||||
{
|
||||
if (
|
||||
@@ -156,26 +156,26 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap
|
||||
}
|
||||
// Found it in the cache
|
||||
auto Idx = m_CacheOrder[i];
|
||||
|
||||
|
||||
// Move to front:
|
||||
for (size_t j = i; j > 0; j--)
|
||||
{
|
||||
m_CacheOrder[j] = m_CacheOrder[j - 1];
|
||||
}
|
||||
m_CacheOrder[0] = Idx;
|
||||
|
||||
|
||||
// Use the cached data:
|
||||
memcpy(a_HeightMap, m_CacheData[Idx].m_HeightMap, sizeof(a_HeightMap));
|
||||
|
||||
|
||||
m_NumHits++;
|
||||
m_TotalChain += i;
|
||||
return;
|
||||
} // for i - cache
|
||||
|
||||
|
||||
// Not in the cache:
|
||||
m_NumMisses++;
|
||||
m_HeiGenToCache->GenHeightMap(a_ChunkX, a_ChunkZ, a_HeightMap);
|
||||
|
||||
|
||||
// Insert it as the first item in the MRU order:
|
||||
auto Idx = m_CacheOrder[m_CacheSize - 1];
|
||||
for (auto i = m_CacheSize - 1; i > 0; i--)
|
||||
@@ -341,7 +341,7 @@ void cHeiGenClassic::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightM
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
const float xx = static_cast<float>(a_ChunkX * cChunkDef::Width + x);
|
||||
|
||||
|
||||
HEIGHTTYPE hei = static_cast<HEIGHTTYPE>(Clamp(static_cast<int>(64 + (GetNoise(xx * 0.05f, zz * 0.05f) * 16)), 10, 250));
|
||||
cChunkDef::SetHeight(a_HeightMap, x, z, hei);
|
||||
} // for x
|
||||
@@ -474,7 +474,7 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
|
||||
/* biMesa */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 70}, // 165
|
||||
/* biMesaPlateauF */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80},
|
||||
/* biMesaPlateau */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80},
|
||||
|
||||
|
||||
// biomes 40 .. 128 are unused, 89 empty placeholders here:
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 40 .. 49
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 50 .. 59
|
||||
@@ -485,22 +485,22 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 100 .. 109
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 110 .. 119
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 120 .. 128
|
||||
|
||||
|
||||
/* biSunflowerPlains */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 129
|
||||
/* biDesertM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 130
|
||||
/* biExtremeHillsM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 131
|
||||
/* biFlowerForest */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 132
|
||||
/* biTaigaM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 133
|
||||
/* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134
|
||||
|
||||
|
||||
// Biomes 135 .. 139 unused, 5 empty placeholders here:
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 135 .. 139
|
||||
|
||||
|
||||
/* biIcePlainsSpikes */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 140
|
||||
|
||||
|
||||
// Biomes 141 .. 148 unused, 8 empty placeholders here:
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 141 .. 148
|
||||
|
||||
|
||||
/* biJungleM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 149
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 150
|
||||
/* biJungleEdgeM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 151
|
||||
@@ -535,13 +535,13 @@ void cHeiGenBiomal::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMa
|
||||
m_BiomeGen->GenBiomes(a_ChunkX + x, a_ChunkZ + z, Biomes[x + 1][z + 1]);
|
||||
} // for x
|
||||
} // for z
|
||||
|
||||
|
||||
/*
|
||||
_X 2013_04_22:
|
||||
There's no point in precalculating the entire perlin noise arrays, too many values are calculated uselessly,
|
||||
resulting in speed DEcrease.
|
||||
*/
|
||||
|
||||
|
||||
//*
|
||||
// Linearly interpolate 4x4 blocks of heightmap:
|
||||
// Must be done on a floating point datatype, else the results are ugly!
|
||||
@@ -556,7 +556,7 @@ void cHeiGenBiomal::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMa
|
||||
}
|
||||
}
|
||||
LinearUpscale2DArrayInPlace<17, 17, STEPX, STEPZ>(Height);
|
||||
|
||||
|
||||
// Copy into the heightmap
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
@@ -566,7 +566,7 @@ void cHeiGenBiomal::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMa
|
||||
}
|
||||
}
|
||||
//*/
|
||||
|
||||
|
||||
/*
|
||||
// For each height, go through neighboring biomes and add up their idea of height:
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
@@ -615,7 +615,7 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX,
|
||||
Sum += WeightX + WeightZ;
|
||||
} // for x
|
||||
} // for z
|
||||
|
||||
|
||||
// For each biome type that has a nonzero count, calc its height and add it:
|
||||
if (Sum > 0)
|
||||
{
|
||||
@@ -628,7 +628,7 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Sanity checks for biome parameters, enable them to check the biome param table in runtime (slow):
|
||||
ASSERT(m_GenParam[i].m_HeightFreq1 >= 0);
|
||||
@@ -638,7 +638,7 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX,
|
||||
ASSERT(m_GenParam[i].m_HeightFreq3 >= 0);
|
||||
ASSERT(m_GenParam[i].m_HeightFreq3 < 1000);
|
||||
*/
|
||||
|
||||
|
||||
NOISE_DATATYPE oct1 = m_Noise.CubicNoise2D(BlockX * m_GenParam[i].m_HeightFreq1, BlockZ * m_GenParam[i].m_HeightFreq1) * m_GenParam[i].m_HeightAmp1;
|
||||
NOISE_DATATYPE oct2 = m_Noise.CubicNoise2D(BlockX * m_GenParam[i].m_HeightFreq2, BlockZ * m_GenParam[i].m_HeightFreq2) * m_GenParam[i].m_HeightAmp2;
|
||||
NOISE_DATATYPE oct3 = m_Noise.CubicNoise2D(BlockX * m_GenParam[i].m_HeightFreq3, BlockZ * m_GenParam[i].m_HeightFreq3) * m_GenParam[i].m_HeightAmp3;
|
||||
@@ -647,7 +647,7 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX,
|
||||
NOISE_DATATYPE res = Height / Sum;
|
||||
return std::min(static_cast<NOISE_DATATYPE>(250), std::max(res, static_cast<NOISE_DATATYPE>(5)));
|
||||
}
|
||||
|
||||
|
||||
// No known biome around? Weird. Return a bogus value:
|
||||
ASSERT(!"cHeiGenBiomal: Biome sum failed, no known biome around");
|
||||
return 5;
|
||||
@@ -756,7 +756,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void InitializeHeightGen(cIniFile & a_IniFile)
|
||||
{
|
||||
// No settings available
|
||||
@@ -872,7 +872,7 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB
|
||||
LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
|
||||
HeightGenName = "Biomal";
|
||||
}
|
||||
|
||||
|
||||
a_CacheOffByDefault = false;
|
||||
cTerrainHeightGenPtr res;
|
||||
if (NoCaseCompare(HeightGenName, "Flat") == 0)
|
||||
@@ -944,7 +944,7 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB
|
||||
a_IniFile.SetValue("Generator", "HeightGen", "Biomal");
|
||||
return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
|
||||
}
|
||||
|
||||
|
||||
// Read the settings:
|
||||
res->InitializeHeightGen(a_IniFile);
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@ class cHeiGenCache :
|
||||
public:
|
||||
cHeiGenCache(cTerrainHeightGenPtr a_HeiGenToCache, size_t a_CacheSize);
|
||||
~cHeiGenCache();
|
||||
|
||||
|
||||
// cTerrainHeightGen overrides:
|
||||
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
|
||||
virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override;
|
||||
|
||||
|
||||
/** Retrieves height at the specified point in the cache, returns true if found, false if not found */
|
||||
bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height);
|
||||
|
||||
|
||||
protected:
|
||||
struct sCacheData
|
||||
{
|
||||
@@ -45,15 +45,15 @@ protected:
|
||||
int m_ChunkZ;
|
||||
cChunkDef::HeightMap m_HeightMap;
|
||||
} ;
|
||||
|
||||
|
||||
/** The terrain height generator that is being cached. */
|
||||
cTerrainHeightGenPtr m_HeiGenToCache;
|
||||
|
||||
|
||||
// To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data
|
||||
size_t m_CacheSize;
|
||||
size_t * m_CacheOrder; // MRU-ized order, indices into m_CacheData array
|
||||
sCacheData * m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used
|
||||
|
||||
|
||||
// Cache statistics
|
||||
size_t m_NumHits;
|
||||
size_t m_NumMisses;
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
// cTerrainHeightGen overrides:
|
||||
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
|
||||
virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override;
|
||||
|
||||
|
||||
/** Retrieves height at the specified point in the cache, returns true if found, false if not found */
|
||||
bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height);
|
||||
|
||||
@@ -102,7 +102,7 @@ class cHeiGenFlat :
|
||||
{
|
||||
public:
|
||||
cHeiGenFlat(void) : m_Height(5) {}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
HEIGHTTYPE m_Height;
|
||||
@@ -121,7 +121,7 @@ class cHeiGenClassic :
|
||||
{
|
||||
public:
|
||||
cHeiGenClassic(int a_Seed);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_Seed;
|
||||
@@ -129,7 +129,7 @@ protected:
|
||||
float m_HeightFreq1, m_HeightAmp1;
|
||||
float m_HeightFreq2, m_HeightAmp2;
|
||||
float m_HeightFreq3, m_HeightAmp3;
|
||||
|
||||
|
||||
float GetNoise(float x, float y);
|
||||
|
||||
// cTerrainHeightGen overrides:
|
||||
@@ -146,14 +146,14 @@ class cHeiGenMountains :
|
||||
{
|
||||
public:
|
||||
cHeiGenMountains(int a_Seed);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_Seed;
|
||||
cRidgedMultiNoise m_MountainNoise;
|
||||
cRidgedMultiNoise m_DitchNoise;
|
||||
cPerlinNoise m_Perlin;
|
||||
|
||||
|
||||
// cTerrainHeightGen overrides:
|
||||
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
|
||||
virtual void InitializeHeightGen(cIniFile & a_IniFile) override;
|
||||
@@ -189,7 +189,7 @@ protected:
|
||||
|
||||
cNoise m_Noise;
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
|
||||
|
||||
// Per-biome terrain generator parameters:
|
||||
struct sGenParam
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
m_BoundingBox(a_BoundingBox)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~cMineShaft() {}
|
||||
|
||||
/** Returns true if this mineshaft intersects the specified cuboid */
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxSystemSize,
|
||||
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
friend class cMineShaft;
|
||||
friend class cMineShaftDirtRoom;
|
||||
@@ -33,14 +33,14 @@ protected:
|
||||
friend class cMineShaftCrossing;
|
||||
friend class cMineShaftStaircase;
|
||||
class cMineShaftSystem; // fwd: MineShafts.cpp
|
||||
|
||||
|
||||
cNoise m_Noise;
|
||||
int m_GridSize; ///< Average spacing of the systems
|
||||
int m_MaxSystemSize; ///< Maximum blcok size of a mineshaft system
|
||||
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
||||
int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor
|
||||
int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing
|
||||
|
||||
|
||||
// cGridStructGen overrides:
|
||||
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
|
||||
} ;
|
||||
|
||||
@@ -24,21 +24,21 @@ class cNoise3DGenerator :
|
||||
public cChunkGenerator::cGenerator
|
||||
{
|
||||
typedef cChunkGenerator::cGenerator super;
|
||||
|
||||
|
||||
public:
|
||||
cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator);
|
||||
virtual ~cNoise3DGenerator();
|
||||
|
||||
|
||||
virtual void Initialize(cIniFile & a_IniFile) override;
|
||||
virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||
virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
|
||||
protected:
|
||||
// Linear interpolation step sizes, must be divisors of cChunkDef::Width and cChunkDef::Height, respectively:
|
||||
static const int UPSCALE_X = 4;
|
||||
static const int UPSCALE_Y = 8;
|
||||
static const int UPSCALE_Z = 4;
|
||||
|
||||
|
||||
// Linear interpolation buffer dimensions, calculated from the step sizes:
|
||||
static const int DIM_X = 1 + cChunkDef::Width / UPSCALE_X;
|
||||
static const int DIM_Y = 1 + cChunkDef::Height / UPSCALE_Y;
|
||||
@@ -49,7 +49,7 @@ protected:
|
||||
|
||||
/** The noise used for heightmap directing. */
|
||||
cOctavedNoise<cInterp5DegNoise> m_Cubic;
|
||||
|
||||
|
||||
int m_SeaLevel;
|
||||
NOISE_DATATYPE m_HeightAmplification;
|
||||
NOISE_DATATYPE m_MidPoint; // Where the vertical "center" of the noise should be
|
||||
@@ -57,13 +57,13 @@ protected:
|
||||
NOISE_DATATYPE m_FrequencyY;
|
||||
NOISE_DATATYPE m_FrequencyZ;
|
||||
NOISE_DATATYPE m_AirThreshold;
|
||||
|
||||
|
||||
/** Generates the 3D noise array used for terrain generation; a_Noise is of ChunkData-size */
|
||||
void GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DATATYPE * a_Noise);
|
||||
|
||||
|
||||
/** Updates heightmap based on the chunk's contents */
|
||||
void UpdateHeightmap(cChunkDesc & a_ChunkDesc);
|
||||
|
||||
|
||||
/** Composes terrain - adds dirt, grass and sand */
|
||||
void ComposeTerrain(cChunkDesc & a_ChunkDesc);
|
||||
} ;
|
||||
@@ -92,7 +92,7 @@ protected:
|
||||
|
||||
/** Heightmap-like noise used to provide variance for low-amplitude biomes. */
|
||||
cOctavedNoise<cInterpolNoise<Interp5Deg>> m_BaseNoise;
|
||||
|
||||
|
||||
/** The main parameter of the generator, specifies the slope of the vertical linear gradient.
|
||||
A higher value means a steeper slope and a smaller total amplitude of the generated terrain. */
|
||||
NOISE_DATATYPE m_HeightAmplification;
|
||||
@@ -116,16 +116,16 @@ protected:
|
||||
|
||||
// Threshold for when the values are considered air:
|
||||
NOISE_DATATYPE m_AirThreshold;
|
||||
|
||||
|
||||
// Cache for the last calculated chunk (reused between heightmap and composition queries):
|
||||
int m_LastChunkX;
|
||||
int m_LastChunkZ;
|
||||
NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // x + 17 * z + 17 * 17 * y
|
||||
|
||||
|
||||
|
||||
|
||||
/** Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords are equal to coords given */
|
||||
void GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
|
||||
// cTerrainHeightGen overrides:
|
||||
virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeShapeGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); }
|
||||
@@ -165,7 +165,7 @@ protected:
|
||||
|
||||
/** The underlying biome generator. */
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
|
||||
|
||||
/** Block height of the sealevel, used for composing the terrain. */
|
||||
int m_SeaLevel;
|
||||
|
||||
@@ -185,7 +185,7 @@ protected:
|
||||
|
||||
// Threshold for when the values are considered air:
|
||||
NOISE_DATATYPE m_AirThreshold;
|
||||
|
||||
|
||||
// Cache for the last calculated chunk (reused between heightmap and composition queries):
|
||||
int m_LastChunkX;
|
||||
int m_LastChunkZ;
|
||||
@@ -196,8 +196,8 @@ protected:
|
||||
|
||||
/** The sum of m_Weight[]. */
|
||||
NOISE_DATATYPE m_WeightSum;
|
||||
|
||||
|
||||
|
||||
|
||||
/** Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords are equal to coords given */
|
||||
void GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
@@ -206,7 +206,7 @@ protected:
|
||||
|
||||
/** Returns the parameters for the specified biome. */
|
||||
void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint);
|
||||
|
||||
|
||||
// cTerrainShapeGen overrides:
|
||||
virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override;
|
||||
virtual void InitializeShapeGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); }
|
||||
|
||||
@@ -84,7 +84,7 @@ Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
|
||||
cPiece::cConnector cPiece::RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const
|
||||
{
|
||||
cPiece::cConnector res(a_Connector);
|
||||
|
||||
|
||||
// Rotate the res connector:
|
||||
switch (a_NumCCWRotations)
|
||||
{
|
||||
@@ -113,12 +113,12 @@ cPiece::cConnector cPiece::RotateMoveConnector(const cConnector & a_Connector, i
|
||||
}
|
||||
}
|
||||
res.m_Pos = RotatePos(a_Connector.m_Pos, a_NumCCWRotations);
|
||||
|
||||
|
||||
// Move the res connector:
|
||||
res.m_Pos.x += a_MoveX;
|
||||
res.m_Pos.y += a_MoveY;
|
||||
res.m_Pos.z += a_MoveZ;
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockZ, c
|
||||
{
|
||||
m_PiecePool.Reset();
|
||||
int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7;
|
||||
|
||||
|
||||
// Choose a random one of the starting pieces:
|
||||
cPieces StartingPieces = m_PiecePool.GetStartingPieces();
|
||||
int Total = 0;
|
||||
@@ -291,7 +291,7 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockZ, c
|
||||
StartingPiece = StartingPieces[static_cast<size_t>(rnd) % StartingPieces.size()];
|
||||
}
|
||||
rnd = rnd >> 16;
|
||||
|
||||
|
||||
// Choose a random supported rotation:
|
||||
int Rotations[4] = {0};
|
||||
int NumRotations = 1;
|
||||
@@ -344,7 +344,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
/* XM */ { 0, 0, 3, 1, 2, 0},
|
||||
/* XP */ { 0, 0, 1, 3, 0, 2},
|
||||
};
|
||||
|
||||
|
||||
// Get a list of available connections:
|
||||
const int * RotTable = DirectionRotationTable[a_Connector.m_Direction];
|
||||
cConnections Connections;
|
||||
@@ -362,7 +362,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Try fitting each of the piece's connector:
|
||||
cPiece::cConnectors Connectors = (*itrP)->GetConnectors();
|
||||
auto verticalLimit = (*itrP)->GetVerticalLimit();
|
||||
@@ -402,7 +402,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
return false;
|
||||
}
|
||||
ASSERT(WeightTotal > 0);
|
||||
|
||||
|
||||
// Choose a random connection from the list, based on the weights:
|
||||
int rnd = (m_Noise.IntNoise3DInt(a_Connector.m_Pos.x, a_Connector.m_Pos.y, a_Connector.m_Pos.z) / 7) % WeightTotal;
|
||||
size_t ChosenIndex = 0;
|
||||
@@ -416,13 +416,13 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
}
|
||||
}
|
||||
cConnection & Conn = Connections[ChosenIndex];
|
||||
|
||||
|
||||
// Place the piece:
|
||||
Vector3i NewPos = Conn.m_Piece->RotatePos(Conn.m_Connector.m_Pos, Conn.m_NumCCWRotations);
|
||||
ConnPos -= NewPos;
|
||||
cPlacedPiece * PlacedPiece = new cPlacedPiece(&a_ParentPiece, *(Conn.m_Piece), ConnPos, Conn.m_NumCCWRotations);
|
||||
a_OutPieces.push_back(PlacedPiece);
|
||||
|
||||
|
||||
// Add the new piece's connectors to the list of free connectors:
|
||||
cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors();
|
||||
for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
|
||||
@@ -434,7 +434,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
}
|
||||
a_OutConnectors.push_back(cFreeConnector(PlacedPiece, Conn.m_Piece->RotateMoveConnector(*itr, Conn.m_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z)));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -538,10 +538,10 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth,
|
||||
{
|
||||
a_OutPieces.clear();
|
||||
cFreeConnectors ConnectorPool;
|
||||
|
||||
|
||||
// Place the starting piece:
|
||||
a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockZ, ConnectorPool));
|
||||
|
||||
|
||||
/*
|
||||
// DEBUG:
|
||||
printf("Placed the starting piece at {%d, %d, %d}\n", a_BlockX, a_BlockY, a_BlockZ);
|
||||
@@ -554,7 +554,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth,
|
||||
);
|
||||
DebugConnectorPool(ConnectorPool, 0);
|
||||
//*/
|
||||
|
||||
|
||||
// Place pieces at the available connectors:
|
||||
/*
|
||||
Instead of removing them one by one from the pool, we process them sequentially and take note of the last
|
||||
|
||||
@@ -33,20 +33,20 @@ class cPiece
|
||||
public:
|
||||
// Force a virtual destructor in all descendants
|
||||
virtual ~cPiece() {}
|
||||
|
||||
|
||||
struct cConnector
|
||||
{
|
||||
/** Position relative to the piece */
|
||||
Vector3i m_Pos;
|
||||
|
||||
|
||||
/** Type of the connector. Any arbitrary number; the generator connects only connectors of opposite
|
||||
(negative) types. */
|
||||
int m_Type;
|
||||
|
||||
|
||||
/** Direction in which the connector is facing.
|
||||
Will be matched by the opposite direction for the connecting connector. */
|
||||
eBlockFace m_Direction;
|
||||
|
||||
|
||||
cConnector(int a_X, int a_Y, int a_Z, int a_Type, eBlockFace a_Direction);
|
||||
cConnector(const Vector3i & a_Pos, int a_Type, eBlockFace a_Direction);
|
||||
};
|
||||
@@ -117,15 +117,15 @@ public:
|
||||
/** Returns all of the available connectors that the piece has.
|
||||
Each connector has a (relative) position in the piece, and a type associated with it. */
|
||||
virtual cConnectors GetConnectors(void) const = 0;
|
||||
|
||||
|
||||
/** Returns the dimensions of this piece.
|
||||
The dimensions cover the entire piece, there is no block that the piece generates outside of this size. */
|
||||
virtual Vector3i GetSize(void) const = 0;
|
||||
|
||||
|
||||
/** Returns the "hitbox" of this piece.
|
||||
A hitbox is what is compared and must not intersect other pieces' hitboxes when generating. */
|
||||
virtual cCuboid GetHitBox(void) const = 0;
|
||||
|
||||
|
||||
/** Returns true if the piece can be rotated CCW the specific number of 90-degree turns. */
|
||||
virtual bool CanRotateCCW(int a_NumRotations) const = 0;
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void SetVerticalStrategy(cVerticalStrategyPtr a_VerticalStrategy)
|
||||
{
|
||||
m_VerticalStrategy = a_VerticalStrategy;
|
||||
@@ -170,10 +170,10 @@ public:
|
||||
|
||||
/** Returns a copy of the connector that is rotated and then moved by the specified amounts. */
|
||||
cConnector RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const;
|
||||
|
||||
|
||||
/** Returns the hitbox after the specified number of rotations and moved so that a_MyConnector is placed at a_ToConnectorPos. */
|
||||
cCuboid RotateHitBoxToConnector(const cConnector & a_MyConnector, const Vector3i & a_ToConnectorPos, int a_NumCCWRotations) const;
|
||||
|
||||
|
||||
/** Returns the hitbox after the specified number of CCW rotations and moved by the specified amounts. */
|
||||
cCuboid RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const;
|
||||
};
|
||||
@@ -198,15 +198,15 @@ class cPiecePool
|
||||
public:
|
||||
// Force a virtual destructor in all descendants:
|
||||
virtual ~cPiecePool() {}
|
||||
|
||||
|
||||
/** Returns a list of pieces that contain the specified connector type.
|
||||
The cPiece pointers returned are managed by the pool and the caller doesn't free them. */
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) = 0;
|
||||
|
||||
|
||||
/** Returns the pieces that should be used as the starting point.
|
||||
Multiple starting points are supported, one of the returned piece will be chosen. */
|
||||
virtual cPieces GetStartingPieces(void) = 0;
|
||||
|
||||
|
||||
/** Returns the relative weight with which the a_NewPiece is to be selected for placing under a_PlacedPiece through a_ExistingConnector.
|
||||
a_ExistingConnector is the original connector, before any movement or rotation is applied to it.
|
||||
This allows the pool to tweak the piece's chances, based on the previous pieces in the tree and the connector used.
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the relative weight with which the a_NewPiece is to be selected for placing as the first piece.
|
||||
This allows the pool to tweak the piece's chances.
|
||||
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will not be chosen.
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
/** Called after a piece is placed, to notify the pool that it has been used.
|
||||
The pool may adjust the pieces it will return the next time. */
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) = 0;
|
||||
|
||||
|
||||
/** Called when the pool has finished the current structure and should reset any piece-counters it has
|
||||
for a new structure. */
|
||||
virtual void Reset(void) = 0;
|
||||
@@ -247,7 +247,7 @@ class cPlacedPiece
|
||||
{
|
||||
public:
|
||||
cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations);
|
||||
|
||||
|
||||
const cPlacedPiece * GetParent (void) const { return m_Parent; }
|
||||
const cPiece & GetPiece (void) const { return *m_Piece; }
|
||||
const Vector3i & GetCoords (void) const { return m_Coords; }
|
||||
@@ -255,23 +255,23 @@ public:
|
||||
const cCuboid & GetHitBox (void) const { return m_HitBox; }
|
||||
int GetDepth (void) const { return m_Depth; }
|
||||
bool HasBeenMovedToGround(void) const { return m_HasBeenMovedToGround; }
|
||||
|
||||
|
||||
/** Returns the coords as a modifiable object. */
|
||||
Vector3i & GetCoords(void) { return m_Coords; }
|
||||
|
||||
|
||||
/** Returns the connector at the specified index, rotated in the actual placement.
|
||||
Undefined behavior if a_Index is out of range. */
|
||||
cPiece::cConnector GetRotatedConnector(size_t a_Index) const;
|
||||
|
||||
|
||||
/** Returns a copy of the specified connector, modified to account for the translation and rotation for
|
||||
this placement. */
|
||||
cPiece::cConnector GetRotatedConnector(const cPiece::cConnector & a_Connector) const;
|
||||
|
||||
|
||||
/** Moves the placed piece Y-wise by the specified offset.
|
||||
Sets m_HasBeenMovedToGround to true, too.
|
||||
Used eg. by village houses. */
|
||||
void MoveToGroundBy(int a_OffsetY);
|
||||
|
||||
|
||||
protected:
|
||||
const cPlacedPiece * m_Parent;
|
||||
const cPiece * m_Piece;
|
||||
@@ -279,7 +279,7 @@ protected:
|
||||
int m_NumCCWRotations;
|
||||
cCuboid m_HitBox; // Hitbox of the placed piece, in world coords
|
||||
int m_Depth; // Depth in the generated piece tree
|
||||
|
||||
|
||||
/** Set to true once the piece has been moved Y-wise.
|
||||
Used eg. by village houses. */
|
||||
bool m_HasBeenMovedToGround;
|
||||
@@ -295,11 +295,11 @@ class cPieceGenerator
|
||||
{
|
||||
public:
|
||||
cPieceGenerator(cPiecePool & a_PiecePool, int a_Seed);
|
||||
|
||||
|
||||
/** Cleans up all the memory used by the placed pieces.
|
||||
Call this utility function instead of freeing the items on your own. */
|
||||
static void FreePieces(cPlacedPieces & a_PlacedPieces);
|
||||
|
||||
|
||||
protected:
|
||||
/** The type used for storing a connection from one piece to another, while building the piece tree. */
|
||||
struct cConnection
|
||||
@@ -308,17 +308,17 @@ protected:
|
||||
cPiece::cConnector m_Connector; // The piece's connector being used (relative non-rotated coords)
|
||||
int m_NumCCWRotations; // Number of rotations necessary to match the two connectors
|
||||
int m_Weight; // Relative chance that this connection will be chosen
|
||||
|
||||
|
||||
cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations, int a_Weight);
|
||||
};
|
||||
typedef std::vector<cConnection> cConnections;
|
||||
|
||||
|
||||
/** The type used for storing a pool of connectors that will be attempted to expand by another piece. */
|
||||
struct cFreeConnector
|
||||
{
|
||||
cPlacedPiece * m_Piece;
|
||||
cPiece::cConnector m_Connector;
|
||||
|
||||
|
||||
cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector);
|
||||
};
|
||||
typedef std::vector<cFreeConnector> cFreeConnectors;
|
||||
@@ -328,11 +328,11 @@ protected:
|
||||
cNoise m_Noise;
|
||||
int m_Seed;
|
||||
|
||||
|
||||
|
||||
/** Selects a starting piece and places it, including its height and rotation.
|
||||
Also puts the piece's connectors in a_OutConnectors. */
|
||||
cPlacedPiece * PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors);
|
||||
|
||||
|
||||
/** Tries to place a new piece at the specified (placed) connector. Returns true if successful. */
|
||||
bool TryPlacePieceAtConnector(
|
||||
const cPlacedPiece & a_ParentPiece, // The existing piece to a new piece should be placed
|
||||
@@ -355,7 +355,7 @@ protected:
|
||||
int a_NumCCWRotations, // Number of rotations for the new piece to align the connector
|
||||
const cPlacedPieces & a_OutPieces // All the already-placed pieces to check
|
||||
);
|
||||
|
||||
|
||||
/** DEBUG: Outputs all the connectors in the pool into stdout.
|
||||
a_NumProcessed signals the number of connectors from the pool that should be considered processed (not listed). */
|
||||
void DebugConnectorPool(const cPieceGenerator::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed);
|
||||
@@ -388,7 +388,7 @@ class cDFSPieceGenerator :
|
||||
{
|
||||
public:
|
||||
cDFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed);
|
||||
|
||||
|
||||
/** Generates a placement for pieces at the specified coords.
|
||||
The Y coord is generated automatically based on the starting piece that is chosen.
|
||||
Caller must free each individual cPlacedPiece in a_OutPieces using cPieceGenerator::FreePieces(). */
|
||||
|
||||
@@ -58,7 +58,7 @@ protected:
|
||||
|
||||
/** The underlying biome generator that defines whether the structure is created or not */
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
|
||||
|
||||
/** The underlying height generator, used to position the prefabs crossing chunk borders if they are set to FitGround. */
|
||||
cTerrainHeightGenPtr m_HeightGen;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ static const cPrefab::sDef g_TestPrefabDef =
|
||||
// Hitbox (relative to bounding box):
|
||||
0, 0, 0, // MinX, MinY, MinZ
|
||||
6, 5, 6, // MaxX, MaxY, MaxZ
|
||||
|
||||
|
||||
// Block definitions:
|
||||
".: 0: 0\n" /* 0 */
|
||||
"a:112: 0\n" /* netherbrick */
|
||||
@@ -86,17 +86,17 @@ static const cPrefab::sDef g_TestPrefabDef =
|
||||
"a.....a"
|
||||
"a.....a"
|
||||
"aaaaaaa",
|
||||
|
||||
|
||||
// Connections:
|
||||
"0: 0, 3, 2: 4\n"
|
||||
"0: 2, 3, 0: 2\n",
|
||||
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotations */
|
||||
|
||||
|
||||
// Merge strategy:
|
||||
cBlockArea::msImprint,
|
||||
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
|
||||
@@ -108,7 +108,7 @@ static const cPrefab::sDef g_TestPrefabDef =
|
||||
|
||||
// AddWeightIfSame:
|
||||
1000,
|
||||
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
};
|
||||
@@ -139,7 +139,7 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
|
||||
ParseBlockImage(cm, a_Def.m_Image);
|
||||
ParseConnectors(a_Def.m_Connectors);
|
||||
ParseDepthWeight(a_Def.m_DepthWeight);
|
||||
|
||||
|
||||
AddRotatedBlockAreas();
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ void cPrefab::AddRotatedBlockAreas(void)
|
||||
m_BlockArea[1].CopyFrom(m_BlockArea[0]);
|
||||
m_BlockArea[1].RotateCCW();
|
||||
}
|
||||
|
||||
|
||||
// 2 rotations are the same as mirroring twice; mirroring is faster because it has no reallocations
|
||||
if ((m_AllowedRotations & 0x02) != 0)
|
||||
{
|
||||
@@ -221,7 +221,7 @@ void cPrefab::AddRotatedBlockAreas(void)
|
||||
m_BlockArea[2].MirrorXY();
|
||||
m_BlockArea[2].MirrorYZ();
|
||||
}
|
||||
|
||||
|
||||
// 3 CCW rotations = 1 CW rotation:
|
||||
if ((m_AllowedRotations & 0x04) != 0)
|
||||
{
|
||||
@@ -250,7 +250,7 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumR
|
||||
int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width;
|
||||
Placement.Move(-ChunkStartX, 0, -ChunkStartZ);
|
||||
const cBlockArea & Image = m_BlockArea[a_NumRotations];
|
||||
|
||||
|
||||
// If the placement is outside this chunk, bail out:
|
||||
if (
|
||||
(Placement.x > cChunkDef::Width) || (Placement.x + Image.GetSizeX() < 0) ||
|
||||
@@ -259,10 +259,10 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumR
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Write the image:
|
||||
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
|
||||
|
||||
|
||||
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
|
||||
if (m_ShouldExtendFloor)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ int cPrefab::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cC
|
||||
// Use the default or per-depth weight:
|
||||
cDepthWeight::const_iterator itr = m_DepthWeight.find(a_PlacedPiece.GetDepth() + 1);
|
||||
int res = (itr == m_DepthWeight.end()) ? m_DefaultWeight : itr->second;
|
||||
|
||||
|
||||
// If the piece is the same as the parent, apply the m_AddWeightIfSame modifier:
|
||||
const cPiece * ParentPiece = &a_PlacedPiece.GetPiece();
|
||||
const cPiece * ThisPiece = this;
|
||||
@@ -378,14 +378,14 @@ void cPrefab::SetAllowedRotations(int a_AllowedRotations)
|
||||
void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef)
|
||||
{
|
||||
ASSERT(a_CharMapDef != nullptr);
|
||||
|
||||
|
||||
// Initialize the charmap to all-invalid values:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(a_CharMapOut); i++)
|
||||
{
|
||||
a_CharMapOut[i].m_BlockType = 0;
|
||||
a_CharMapOut[i].m_BlockMeta = 16; // Mark unassigned entries with a meta that is impossible otherwise
|
||||
}
|
||||
|
||||
|
||||
// Process the lines in the definition:
|
||||
AStringVector Lines = StringSplitAndTrim(a_CharMapDef, "\n");
|
||||
for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr)
|
||||
@@ -439,7 +439,7 @@ void cPrefab::ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockIma
|
||||
void cPrefab::ParseConnectors(const char * a_ConnectorsDef)
|
||||
{
|
||||
ASSERT(a_ConnectorsDef != nullptr);
|
||||
|
||||
|
||||
AStringVector Lines = StringSplitAndTrim(a_ConnectorsDef, "\n");
|
||||
for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr)
|
||||
{
|
||||
@@ -460,7 +460,7 @@ void cPrefab::ParseConnectors(const char * a_ConnectorsDef)
|
||||
LOGWARNING("Bad prefab Connector coords definition: \"%s\", skipping.", Defs[1].c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Check that the BlockFace is within range:
|
||||
int BlockFace = atoi(Defs[2].c_str());
|
||||
if ((BlockFace < 0) || (BlockFace >= 6))
|
||||
@@ -489,10 +489,10 @@ void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Split into individual records: "Record | Record | Record"
|
||||
AStringVector Defs = StringSplitAndTrim(a_DepthWeightDef, "|");
|
||||
|
||||
|
||||
// Add each record's contents:
|
||||
for (AStringVector::const_iterator itr = Defs.begin(), end = Defs.end(); itr != end; ++itr)
|
||||
{
|
||||
@@ -503,7 +503,7 @@ void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef)
|
||||
LOGWARNING("Bad prefab DepthWeight record: \"%s\", skipping.", itr->c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Parse depth:
|
||||
int Depth = atoi(Components[0].c_str());
|
||||
if ((Depth == 0) && (Components[0] != "0"))
|
||||
@@ -511,7 +511,7 @@ void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef)
|
||||
LOGWARNING("Bad prefab DepthWeight record, cannot parse depth \"%s\", skipping.", Components[0].c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Parse weight:
|
||||
int Weight = atoi(Components[1].c_str());
|
||||
if ((Weight == 0) && (Components[1] != "0"))
|
||||
@@ -519,7 +519,7 @@ void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef)
|
||||
LOGWARNING("Bad prefab DepthWeight record, cannot parse weight \"%s\", skipping.", Components[1].c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Save to map:
|
||||
ASSERT(m_DepthWeight.find(Depth) == m_DepthWeight.end()); // Not a duplicate
|
||||
m_DepthWeight[Depth] = Weight;
|
||||
|
||||
@@ -37,31 +37,31 @@ public:
|
||||
int m_SizeX;
|
||||
int m_SizeY;
|
||||
int m_SizeZ;
|
||||
|
||||
|
||||
/** The hitbox used for collision-checking between prefabs. Relative to the bounds. */
|
||||
int m_HitboxMinX, m_HitboxMinY, m_HitboxMinZ;
|
||||
int m_HitboxMaxX, m_HitboxMaxY, m_HitboxMaxZ;
|
||||
|
||||
|
||||
/** The mapping between characters in m_Image and the blocktype / blockmeta.
|
||||
Format: "Char: BlockType: BlockMeta \n Char: BlockType : BlockMeta \n ..." */
|
||||
const char * m_CharMap;
|
||||
|
||||
|
||||
/** The actual image to be used for the prefab. Organized YZX (Y changes the least often).
|
||||
Each character represents a single block, the type is mapped through m_CharMap. */
|
||||
const char * m_Image;
|
||||
|
||||
|
||||
/** List of connectors.
|
||||
Format: "Type: X, Y, Z : Direction \n Type : X, Y, Z : Direction \n ...".
|
||||
Type is an arbitrary number, Direction is the BlockFace constant value (0 .. 5). */
|
||||
const char * m_Connectors;
|
||||
|
||||
|
||||
/** Bitmask specifying the allowed rotations.
|
||||
N rotations CCW are allowed if bit N is set. */
|
||||
int m_AllowedRotations;
|
||||
|
||||
|
||||
/** The merge strategy to use while drawing the prefab. */
|
||||
cBlockArea::eMergeStrategy m_MergeStrategy;
|
||||
|
||||
|
||||
/** If set to true, the prefab will extend its lowermost blocks until a solid block is found,
|
||||
thus creating a foundation for the prefab. This is used for houses to be "on the ground", as well as
|
||||
nether fortresses not to float. */
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
|
||||
/** Chance of this piece being used, if no other modifier is active. */
|
||||
int m_DefaultWeight;
|
||||
|
||||
|
||||
/** Chances of this piece being used, per depth of the generated piece tree.
|
||||
The starting piece has a depth of 0, the pieces connected to it are depth 1, etc.
|
||||
The specified depth stands for the depth of the new piece (not the existing already-placed piece),
|
||||
@@ -77,56 +77,56 @@ public:
|
||||
Format: "Depth : Weight | Depth : Weight | Depth : Weight ..."
|
||||
Depths that are not specified will use the m_DefaultWeight value. */
|
||||
const char * m_DepthWeight;
|
||||
|
||||
|
||||
/** The weight to add to this piece's base per-depth chance if the previous piece is the same.
|
||||
Can be positive or negative.
|
||||
This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */
|
||||
int m_AddWeightIfSame;
|
||||
|
||||
|
||||
/** If true, the piece will be moved Y-wise so that its first connector is sitting on the terrain.
|
||||
This is used e. g. for village houses. */
|
||||
bool m_MoveToGround;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Creates a prefab from the provided definition. */
|
||||
cPrefab(const sDef & a_Def);
|
||||
|
||||
|
||||
/** Creates a prefab based on the given BlockArea and allowed rotations. */
|
||||
cPrefab(const cBlockArea & a_Image, int a_AllowedRotations);
|
||||
|
||||
|
||||
/** Creates a prefab based on the given BlockArea. Allowed rotations can be added later on using SetAllowedRotations(). */
|
||||
cPrefab(const cBlockArea & a_Image);
|
||||
|
||||
|
||||
/** Creates a prefab based on the specified block data, using the char-to-block map in a_BlockDefinitions.
|
||||
Allowed rotations can be added later on using SetAllowedRotations(). */
|
||||
cPrefab(const AString & a_BlockDefinitions, const AString & a_BlockData, int a_SizeX, int a_SizeY, int a_SizeZ);
|
||||
|
||||
|
||||
/** Draws the prefab into the specified chunk, according to the placement stored in the PlacedPiece. */
|
||||
void Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const;
|
||||
|
||||
|
||||
/** Draws the prefab into the specified chunks, according to the specified placement and rotations. */
|
||||
void Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumRotations) const;
|
||||
|
||||
|
||||
/** Returns true if the prefab has any connector of the specified type. */
|
||||
bool HasConnectorType(int a_ConnectorType) const;
|
||||
|
||||
|
||||
/** Returns the weight (chance) of this prefab generating as the next piece after the specified placed piece.
|
||||
PiecePool implementations can use this for their GetPieceWeight() implementations. */
|
||||
int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector) const;
|
||||
|
||||
|
||||
/** Sets the (unmodified) DefaultWeight property for this piece. */
|
||||
void SetDefaultWeight(int a_DefaultWeight);
|
||||
|
||||
|
||||
/** Returns the unmodified DefaultWeight property for the piece. */
|
||||
int GetDefaultWeight(void) const { return m_DefaultWeight; }
|
||||
|
||||
|
||||
/** Sets the AddWeightIfSame member, that is used to modify the weight when the previous piece is the same prefab */
|
||||
void SetAddWeightIfSame(int a_AddWeightIfSame) { m_AddWeightIfSame = a_AddWeightIfSame; }
|
||||
|
||||
|
||||
/** Adds the specified connector to the list of connectors this piece supports. */
|
||||
void AddConnector(int a_RelX, int a_RelY, int a_RelZ, eBlockFace a_Direction, int a_Type);
|
||||
|
||||
|
||||
/** Returns whether the prefab should be moved Y-wise to ground before drawing, rather than staying
|
||||
at the coords governed by the connectors. */
|
||||
bool ShouldMoveToGround(void) const { return m_MoveToGround; }
|
||||
@@ -156,30 +156,30 @@ protected:
|
||||
BLOCKTYPE m_BlockType;
|
||||
NIBBLETYPE m_BlockMeta;
|
||||
};
|
||||
|
||||
|
||||
/** Maps letters in the sDef::m_Image onto a sBlockTypeDef block type definition. */
|
||||
typedef sBlockTypeDef CharMap[256];
|
||||
|
||||
|
||||
/** Maps generator tree depth to weight. */
|
||||
typedef std::map<int, int> cDepthWeight;
|
||||
|
||||
|
||||
|
||||
|
||||
/** The cBlockArea that contains the block definitions for the prefab.
|
||||
The index identifies the number of CCW rotations applied (0 = no rotation, 1 = 1 CCW rotation, ...). */
|
||||
cBlockArea m_BlockArea[4];
|
||||
|
||||
|
||||
/** The size of the prefab */
|
||||
Vector3i m_Size;
|
||||
|
||||
|
||||
/** The hitbox used for collision-checking between prefabs. */
|
||||
cCuboid m_HitBox;
|
||||
|
||||
|
||||
/** The connectors through which the piece connects to other pieces */
|
||||
cConnectors m_Connectors;
|
||||
|
||||
|
||||
/** Bitmask, bit N set -> N rotations CCW supported */
|
||||
int m_AllowedRotations;
|
||||
|
||||
|
||||
/** The merge strategy to use when drawing the prefab into a block area */
|
||||
cBlockArea::eMergeStrategy m_MergeStrategy;
|
||||
|
||||
@@ -190,14 +190,14 @@ protected:
|
||||
|
||||
/** Chance of this piece being used, if no other modifier is active. */
|
||||
int m_DefaultWeight;
|
||||
|
||||
|
||||
/** Chances of this piece being used, per depth of the generated piece tree.
|
||||
The starting piece has a depth of 0, the pieces connected to it are depth 1, etc.
|
||||
The specified depth stands for the depth of the new piece (not the existing already-placed piece),
|
||||
so valid depths start at 1.
|
||||
Depths that are not specified will use the m_DefaultWeight value. */
|
||||
cDepthWeight m_DepthWeight;
|
||||
|
||||
|
||||
/** The weight to add to this piece's base per-depth chance if the previous piece is the same.
|
||||
Can be positive or negative.
|
||||
This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */
|
||||
@@ -206,24 +206,24 @@ protected:
|
||||
/** If true, the piece will be moved Y-wise so that its first connector is sitting on the terrain.
|
||||
This is used e. g. for village houses. */
|
||||
bool m_MoveToGround;
|
||||
|
||||
|
||||
|
||||
|
||||
// cPiece overrides:
|
||||
virtual cConnectors GetConnectors(void) const override;
|
||||
virtual Vector3i GetSize(void) const override;
|
||||
virtual cCuboid GetHitBox(void) const override;
|
||||
virtual bool CanRotateCCW(int a_NumRotations) const override;
|
||||
|
||||
|
||||
/** Based on the m_AllowedRotations, adds rotated cBlockAreas to the m_BlockArea array.
|
||||
To be called only from this class's constructor! */
|
||||
void AddRotatedBlockAreas(void);
|
||||
|
||||
|
||||
/** Parses the CharMap in the definition into a CharMap binary data used for translating the definition into BlockArea. */
|
||||
void ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef);
|
||||
|
||||
|
||||
/** Parses the Image in the definition into m_BlockArea[0]'s block types and metas, using the specified CharMap. */
|
||||
void ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockImage);
|
||||
|
||||
|
||||
/** Parses the connectors definition text into m_Connectors member. */
|
||||
void ParseConnectors(const char * a_ConnectorsDef);
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ class cPrefabPiecePool :
|
||||
public:
|
||||
/** Creates an empty instance. Prefabs can be added by calling AddPieceDefs() and AddStartingPieceDefs(). */
|
||||
cPrefabPiecePool(void);
|
||||
|
||||
|
||||
/** Creates a piece pool with prefabs from the specified definitions.
|
||||
If both a_PieceDefs and a_StartingPieceDefs are given, only the a_StartingPieceDefs are used as starting
|
||||
pieces for the pool, and they do not participate in the generation any further.
|
||||
@@ -44,22 +44,22 @@ public:
|
||||
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs,
|
||||
int a_DefaultStartingPieceHeight = -1
|
||||
);
|
||||
|
||||
|
||||
/** Creates a pool and loads the contents of the specified file into it.
|
||||
If a_LogWarnings is true, logs a warning to console when loading fails. */
|
||||
cPrefabPiecePool(const AString & a_FileName, bool a_LogWarnings);
|
||||
|
||||
/** Destroys the pool, freeing all pieces. */
|
||||
~cPrefabPiecePool();
|
||||
|
||||
|
||||
/** Removes and frees all pieces from this pool. */
|
||||
void Clear(void);
|
||||
|
||||
|
||||
/** Adds pieces from the specified definitions into m_AllPieces. Also adds the pieces into
|
||||
the m_PiecesByConnector map.
|
||||
May be called multiple times with different PieceDefs, will add all such pieces. */
|
||||
void AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs);
|
||||
|
||||
|
||||
/** Adds pieces from the specified definitions into m_StartingPieces. Doesn't add them to
|
||||
the m_PiecesByConnector map.
|
||||
May be called multiple times with different PieceDefs, will add all such pieces.
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
size_t a_NumStartingPieceDefs,
|
||||
int a_DefaultPieceHeight = -1
|
||||
);
|
||||
|
||||
|
||||
/** Loads the pieces from the specified file. Returns true if successful, false on error.
|
||||
If a_LogWarnings is true, logs a warning to console when loading fails. */
|
||||
bool LoadFromFile(const AString & a_FileName, bool a_LogWarnings);
|
||||
@@ -132,11 +132,11 @@ protected:
|
||||
/** All the pieces that are allowed for building.
|
||||
This is the list that's used for memory allocation and deallocation for the pieces. */
|
||||
cPieces m_AllPieces;
|
||||
|
||||
|
||||
/** The pieces that are used as starting pieces.
|
||||
This list is not shared and the pieces need deallocation. */
|
||||
cPieces m_StartingPieces;
|
||||
|
||||
|
||||
/** The map that has all pieces by their connector types
|
||||
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
||||
cPiecesMap m_PiecesByConnector;
|
||||
@@ -158,7 +158,7 @@ protected:
|
||||
|
||||
/** The block type used for the village roads if the road is on water. */
|
||||
BLOCKTYPE m_VillageWaterRoadBlockType;
|
||||
|
||||
|
||||
/** The block meta used for the village roads if the road is on water. */
|
||||
NIBBLETYPE m_VillageWaterRoadBlockMeta;
|
||||
|
||||
@@ -196,7 +196,7 @@ protected:
|
||||
const AString & a_PieceName,
|
||||
bool a_LogWarnings
|
||||
);
|
||||
|
||||
|
||||
/** Reads a single piece's connectors from the cubeset file parsed into the specified Lua state.
|
||||
The piece's definition table is expected to be at the top of the Lua stack.
|
||||
Returns true on success, false on failure.
|
||||
|
||||
@@ -22,7 +22,7 @@ struct cRavDefPoint
|
||||
int m_Radius;
|
||||
int m_Top;
|
||||
int m_Bottom;
|
||||
|
||||
|
||||
cRavDefPoint(int a_BlockX, int a_BlockZ, int a_Radius, int a_Top, int a_Bottom) :
|
||||
m_BlockX(a_BlockX),
|
||||
m_BlockZ(a_BlockZ),
|
||||
@@ -46,23 +46,23 @@ class cStructGenRavines::cRavine :
|
||||
|
||||
cRavDefPoints m_Points;
|
||||
|
||||
|
||||
|
||||
/** Generates the shaping defpoints for the ravine, based on the ravine block coords and noise */
|
||||
void GenerateBaseDefPoints(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise);
|
||||
|
||||
|
||||
/** Refines (adds and smooths) defpoints from a_Src into a_Dst */
|
||||
void RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst);
|
||||
|
||||
|
||||
/** Does one round of smoothing, two passes of RefineDefPoints() */
|
||||
void Smooth(void);
|
||||
|
||||
|
||||
/** Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block */
|
||||
void FinishLinear(void);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
cRavine(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_Size, cNoise & a_Noise);
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
/** Exports itself as a SVG line definition */
|
||||
AString ExportAsSVG(int a_Color, int a_OffsetX = 0, int a_OffsetZ = 0) const;
|
||||
@@ -109,11 +109,11 @@ cStructGenRavines::cRavine::cRavine(int a_GridX, int a_GridZ, int a_OriginX, int
|
||||
{
|
||||
// Calculate the ravine shape-defining points:
|
||||
GenerateBaseDefPoints(a_OriginX, a_OriginZ, a_Size, a_Noise);
|
||||
|
||||
|
||||
// Smooth the ravine. Two passes are needed:
|
||||
Smooth();
|
||||
Smooth();
|
||||
|
||||
|
||||
// Linearly interpolate the neighbors so that they're close enough together:
|
||||
FinishLinear();
|
||||
}
|
||||
@@ -126,18 +126,18 @@ void cStructGenRavines::cRavine::GenerateBaseDefPoints(int a_BlockX, int a_Block
|
||||
{
|
||||
// Modify the size slightly to have different-sized ravines (1 / 2 to 1 / 1 of a_Size):
|
||||
a_Size = (512 + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 11 * a_BlockZ, a_BlockX + a_BlockZ) / 17) % 512)) * a_Size / 1024;
|
||||
|
||||
|
||||
// The complete offset of the ravine from its cellpoint, up to 2 * a_Size in each direction
|
||||
int OffsetX = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 0) / 9) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 1000) / 7) % (2 * a_Size)) - 2 * a_Size) / 2;
|
||||
int OffsetZ = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 2000) / 7) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 3000) / 9) % (2 * a_Size)) - 2 * a_Size) / 2;
|
||||
int CenterX = a_BlockX + OffsetX;
|
||||
int CenterZ = a_BlockZ + OffsetZ;
|
||||
|
||||
|
||||
// Get the base angle in which the ravine "axis" goes:
|
||||
float Angle = static_cast<float>((static_cast<float>((a_Noise.IntNoise3DInt(20 * a_BlockX, 70 * a_BlockZ, 6000) / 9) % 16384)) / 16384.0 * M_PI);
|
||||
float xc = sinf(Angle);
|
||||
float zc = cosf(Angle);
|
||||
|
||||
|
||||
// Calculate the definition points and radii:
|
||||
int MaxRadius = static_cast<int>(sqrt(12.0 + ((a_Noise.IntNoise2DInt(61 * a_BlockX, 97 * a_BlockZ) / 13) % a_Size) / 16));
|
||||
int Top = 32 + ((a_Noise.IntNoise2DInt(13 * a_BlockX, 17 * a_BlockZ) / 23) % 32);
|
||||
@@ -234,10 +234,10 @@ void cStructGenRavines::cRavine::FinishLinear(void)
|
||||
// For each segment, use Bresenham's line algorithm to draw a "line" of defpoints
|
||||
// _X 2012_07_20: I tried modifying this algorithm to produce "thick" lines (only one coord change per point)
|
||||
// But the results were about the same as the original, so I disposed of it again - no need to use twice the count of points
|
||||
|
||||
|
||||
cRavDefPoints Pts;
|
||||
std::swap(Pts, m_Points);
|
||||
|
||||
|
||||
m_Points.reserve(Pts.size() * 3);
|
||||
int PrevX = Pts.front().m_BlockX;
|
||||
int PrevZ = Pts.front().m_BlockZ;
|
||||
@@ -299,12 +299,12 @@ AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d, %d L %d, %d\"/>\n",
|
||||
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ - 5, a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ + 5
|
||||
);
|
||||
|
||||
|
||||
// A gray line from the base point to the first point of the ravine, for identification:
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#cfcfcf;stroke-width:1px;\"\nd=\"M %d, %d L %d, %d\"/>\n",
|
||||
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ, a_OffsetX + m_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ
|
||||
);
|
||||
|
||||
|
||||
// Offset guides:
|
||||
if (a_OffsetX > 0)
|
||||
{
|
||||
@@ -344,7 +344,7 @@ void cStructGenRavines::cRavine::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
|
||||
// Cannot intersect, bail out early
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Carve out a cylinder around the xz point, m_Radius in diameter, from Bottom to Top:
|
||||
int RadiusSq = itr->m_Radius * itr->m_Radius; // instead of doing sqrt for each distance, we do sqr of the radius
|
||||
int DifX = BlockStartX - itr->m_BlockX; // substitution for faster calc
|
||||
@@ -358,7 +358,7 @@ void cStructGenRavines::cRavine::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
|
||||
a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE);
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
int DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z);
|
||||
if (DistSq <= RadiusSq)
|
||||
{
|
||||
|
||||
@@ -22,13 +22,13 @@ class cStructGenRavines :
|
||||
|
||||
public:
|
||||
cStructGenRavines(int a_Seed, int a_Size);
|
||||
|
||||
|
||||
protected:
|
||||
class cRavine; // fwd: Ravines.cpp
|
||||
|
||||
|
||||
cNoise m_Noise;
|
||||
int m_Size; // Max size, in blocks, of the ravines generated
|
||||
|
||||
|
||||
|
||||
// cGridStructGen overrides:
|
||||
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
|
||||
|
||||
@@ -18,7 +18,7 @@ class cRoughRavine :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
|
||||
public:
|
||||
cRoughRavine(
|
||||
int a_Seed, size_t a_Size,
|
||||
@@ -44,15 +44,15 @@ public:
|
||||
m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, a_CeilingHeightEdge1, a_FloorHeightEdge1);
|
||||
m_DefPoints[Half].Set(static_cast<float>(a_OriginX), static_cast<float>(a_OriginZ), a_CenterWidth, a_CeilingHeightCenter, a_FloorHeightCenter);
|
||||
m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, a_CeilingHeightEdge2, a_FloorHeightEdge2);
|
||||
|
||||
|
||||
// Calculate the points in between, recursively:
|
||||
SubdivideLine(0, Half);
|
||||
SubdivideLine(Half, Max);
|
||||
|
||||
|
||||
// Initialize the per-height radius modifiers:
|
||||
InitPerHeightRadius(a_GridX, a_GridZ);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
struct sRavineDefPoint
|
||||
{
|
||||
@@ -61,7 +61,7 @@ protected:
|
||||
float m_Radius;
|
||||
float m_Top;
|
||||
float m_Bottom;
|
||||
|
||||
|
||||
void Set(float a_X, float a_Z, float a_Radius, float a_Top, float a_Bottom)
|
||||
{
|
||||
m_X = a_X;
|
||||
@@ -72,21 +72,21 @@ protected:
|
||||
}
|
||||
};
|
||||
typedef std::vector<sRavineDefPoint> sRavineDefPoints;
|
||||
|
||||
|
||||
int m_Seed;
|
||||
|
||||
|
||||
cNoise m_Noise;
|
||||
|
||||
|
||||
int m_MaxSize;
|
||||
|
||||
|
||||
sRavineDefPoints m_DefPoints;
|
||||
|
||||
|
||||
float m_Roughness;
|
||||
|
||||
|
||||
/** Number to add to the radius based on the height. This creates the "ledges" in the ravine walls. */
|
||||
float m_PerHeightRadius[cChunkDef::Height];
|
||||
|
||||
|
||||
|
||||
|
||||
/** Recursively subdivides the line between the points of the specified index.
|
||||
Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half
|
||||
of the new line. */
|
||||
@@ -116,7 +116,7 @@ protected:
|
||||
}
|
||||
size_t MidIdx = (a_Idx1 + a_Idx2) / 2;
|
||||
m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB);
|
||||
|
||||
|
||||
// Recurse the two halves, if they are worth recursing:
|
||||
if (MidIdx - a_Idx1 > 1)
|
||||
{
|
||||
@@ -127,8 +127,8 @@ protected:
|
||||
SubdivideLine(MidIdx, a_Idx2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void InitPerHeightRadius(int a_GridX, int a_GridZ)
|
||||
{
|
||||
int h = 0;
|
||||
@@ -150,8 +150,8 @@ protected:
|
||||
h += NumBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
|
||||
{
|
||||
int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||
@@ -170,7 +170,7 @@ protected:
|
||||
// Cannot intersect, bail out early
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Carve out a cylinder around the xz point, up to (m_Radius + 2) in diameter, from Bottom to Top:
|
||||
// On each height level, use m_PerHeightRadius[] to modify the actual radius used
|
||||
// EnlargedRadiusSq is the square of the radius enlarged by the maximum m_PerHeightRadius offset - anything outside it will never be touched.
|
||||
@@ -186,14 +186,14 @@ protected:
|
||||
a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE);
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
// If the column is outside the enlarged radius, bail out completely
|
||||
float DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z);
|
||||
if (DistSq > RadiusSq)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int Top = std::min(static_cast<int>(ceilf(itr->m_Top)), +cChunkDef::Height);
|
||||
for (int y = std::max(static_cast<int>(floorf(itr->m_Bottom)), 1); y <= Top; y++)
|
||||
{
|
||||
@@ -284,7 +284,7 @@ cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_
|
||||
float CeilingHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 60, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge);
|
||||
float CeilingHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 70, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge);
|
||||
float CeilingHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 80, a_GridZ, m_MinCeilingHeightCenter, m_MaxCeilingHeightCenter);
|
||||
|
||||
|
||||
// Create a ravine:
|
||||
return cStructurePtr(new cRoughRavine(
|
||||
m_Seed,
|
||||
|
||||
@@ -18,7 +18,7 @@ class cRoughRavines :
|
||||
public cGridStructGen
|
||||
{
|
||||
typedef cGridStructGen super;
|
||||
|
||||
|
||||
public:
|
||||
cRoughRavines(
|
||||
int a_Seed,
|
||||
@@ -31,22 +31,22 @@ public:
|
||||
float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter,
|
||||
int a_GridSize, int a_MaxOffset
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
int m_Seed;
|
||||
|
||||
|
||||
/** Maximum size of the ravine, in each of the X / Z axis */
|
||||
int m_MaxSize;
|
||||
|
||||
|
||||
/** Minimum size of the ravine */
|
||||
int m_MinSize;
|
||||
|
||||
/** Maximum width of the ravine's center, in blocks */
|
||||
float m_MaxCenterWidth;
|
||||
|
||||
|
||||
/** Minimum width of the ravine's center, in blocks */
|
||||
float m_MinCenterWidth;
|
||||
|
||||
|
||||
/** Maximum roughness of the ravine */
|
||||
float m_MaxRoughness;
|
||||
|
||||
@@ -55,25 +55,25 @@ protected:
|
||||
|
||||
/** Maximum floor height at the ravine's edge */
|
||||
float m_MaxFloorHeightEdge;
|
||||
|
||||
|
||||
/** Minimum floor height at the ravine's edge */
|
||||
float m_MinFloorHeightEdge;
|
||||
|
||||
|
||||
/** Maximum floor height at the ravine's center */
|
||||
float m_MaxFloorHeightCenter;
|
||||
|
||||
|
||||
/** Minimum floor height at the ravine's center */
|
||||
float m_MinFloorHeightCenter;
|
||||
|
||||
|
||||
/** Maximum ceiling height at the ravine's edge */
|
||||
float m_MaxCeilingHeightEdge;
|
||||
|
||||
|
||||
/** Minimum ceiling height at the ravine's edge */
|
||||
float m_MinCeilingHeightEdge;
|
||||
|
||||
|
||||
/** Maximum ceiling height at the ravine's center */
|
||||
float m_MaxCeilingHeightCenter;
|
||||
|
||||
|
||||
/** Minimum ceiling height at the ravine's center */
|
||||
float m_MinCeilingHeightCenter;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ cTerrainShapeGenPtr cTerrainShapeGen::CreateShapeGen(cIniFile & a_IniFile, cBiom
|
||||
LOGWARN("[Generator] ShapeGen value not set in world.ini, using \"BiomalNoise3D\".");
|
||||
shapeGenName = "BiomalNoise3D";
|
||||
}
|
||||
|
||||
|
||||
// If the shapegen is HeightMap, redirect to older HeightMap-based generators:
|
||||
if (NoCaseCompare(shapeGenName, "HeightMap") == 0)
|
||||
{
|
||||
@@ -133,10 +133,10 @@ cTerrainShapeGenPtr cTerrainShapeGen::CreateShapeGen(cIniFile & a_IniFile, cBiom
|
||||
a_IniFile.SetValue("Generator", "ShapeGen", "BiomalNoise3D");
|
||||
return CreateShapeGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
|
||||
}
|
||||
|
||||
|
||||
// Read the settings:
|
||||
res->InitializeShapeGen(a_IniFile);
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
|
||||
|
||||
cChunkDesc WorkerDesc(ChunkX, ChunkZ);
|
||||
|
||||
|
||||
// Generate trees:
|
||||
for (int x = 0; x <= 2; x++)
|
||||
{
|
||||
@@ -29,14 +29,14 @@ void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
for (int z = 0; z <= 2; z++)
|
||||
{
|
||||
int BaseZ = ChunkZ + z - 1;
|
||||
|
||||
|
||||
cChunkDesc * Dest;
|
||||
|
||||
if ((x != 1) || (z != 1))
|
||||
{
|
||||
Dest = &WorkerDesc;
|
||||
WorkerDesc.SetChunkCoords(BaseX, BaseZ);
|
||||
|
||||
|
||||
// TODO: This may cause a lot of wasted calculations, instead of pulling data out of a single (cChunkDesc) cache
|
||||
|
||||
cChunkDesc::Shape workerShape;
|
||||
@@ -66,7 +66,7 @@ void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideLogs, IgnoredOverflow);
|
||||
} // for z
|
||||
} // for x
|
||||
|
||||
|
||||
// Update the heightmap:
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
@@ -97,9 +97,9 @@ void cStructGenTrees::GenerateSingleTree(
|
||||
{
|
||||
int x = (m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) / 19) % cChunkDef::Width;
|
||||
int z = (m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) / 19) % cChunkDef::Width;
|
||||
|
||||
|
||||
int Height = a_ChunkDesc.GetHeight(x, z);
|
||||
|
||||
|
||||
if ((Height <= 0) || (Height >= 230))
|
||||
{
|
||||
return;
|
||||
@@ -111,7 +111,7 @@ void cStructGenTrees::GenerateSingleTree(
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sSetBlockVector TreeLogs, TreeOther;
|
||||
GetTreeImageByBiome(
|
||||
a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z,
|
||||
@@ -148,7 +148,7 @@ void cStructGenTrees::GenerateSingleTree(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeOther, a_OutsideOther);
|
||||
ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs);
|
||||
}
|
||||
@@ -185,11 +185,11 @@ void cStructGenTrees::ApplyTreeImage(
|
||||
a_ChunkDesc.SetBlockTypeMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
} // switch (GetBlock())
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Outside the chunk, push into a_Overflow.
|
||||
// Don't check if already present there, by separating logs and others we don't need the checks anymore:
|
||||
a_Overflow.push_back(*itr);
|
||||
@@ -279,20 +279,20 @@ void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
|
||||
|
||||
for (int z = -1; z < 2; z++) for (int x = -1; x < 2; x++)
|
||||
{
|
||||
if (((m_Noise.IntNoise2DInt(ChunkX + x, ChunkZ + z) / 17) % 100) > m_Probability)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
cBlockArea Lake;
|
||||
CreateLakeImage(ChunkX + x, ChunkZ + z, a_ChunkDesc.GetMinHeight(), Lake);
|
||||
|
||||
|
||||
int OfsX = Lake.GetOriginX() + x * cChunkDef::Width;
|
||||
int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width;
|
||||
|
||||
|
||||
// Merge the lake into the current data
|
||||
a_ChunkDesc.WriteBlockArea(Lake, OfsX, Lake.GetOriginY(), OfsZ, cBlockArea::msLake);
|
||||
} // for x, z - neighbor chunks
|
||||
@@ -306,7 +306,7 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeH
|
||||
{
|
||||
a_Lake.Create(16, 8, 16);
|
||||
a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy
|
||||
|
||||
|
||||
// Make a random position in the chunk by using a random 16 block XZ offset and random height up to chunk's max height minus 6
|
||||
int MinHeight = std::max(a_MaxLakeHeight - 6, 2);
|
||||
int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11;
|
||||
@@ -318,9 +318,9 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeH
|
||||
Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 512, a_ChunkZ) / 13;
|
||||
// Random height [1 .. MinHeight] with preference to center heights
|
||||
int HeightY = 1 + (((Rnd & 0x1ff) % MinHeight) + (((Rnd >> 9) & 0x1ff) % MinHeight)) / 2;
|
||||
|
||||
|
||||
a_Lake.SetOrigin(OffsetX, HeightY, OffsetZ);
|
||||
|
||||
|
||||
// Hollow out a few bubbles inside the blockarea:
|
||||
int NumBubbles = 4 + ((Rnd >> 18) & 0x03); // 4 .. 7 bubbles
|
||||
BLOCKTYPE * BlockTypes = a_Lake.GetBlockTypes();
|
||||
@@ -371,9 +371,9 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeH
|
||||
}
|
||||
} // for z, x
|
||||
} // for y
|
||||
|
||||
|
||||
// TODO: Turn sponge next to lava into stone
|
||||
|
||||
|
||||
// a_Lake.SaveToSchematicFile(Printf("Lake_%d_%d.schematic", a_ChunkX, a_ChunkZ));
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight();
|
||||
|
||||
const int SEGMENT_HEIGHT = 8;
|
||||
@@ -410,7 +410,7 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
// Interpolate the chunk in 16 * SEGMENT_HEIGHT * 16 "segments", each SEGMENT_HEIGHT blocks high and each linearly interpolated separately.
|
||||
// Have two buffers, one for the lowest floor and one for the highest floor, so that Y-interpolation can be done between them
|
||||
// Then swap the buffers and use the previously-top one as the current-bottom, without recalculating it.
|
||||
|
||||
|
||||
int FloorBuf1[17 * 17];
|
||||
int FloorBuf2[17 * 17];
|
||||
int * FloorHi = FloorBuf1;
|
||||
@@ -418,7 +418,7 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
int BaseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||
int BaseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||
int BaseY = 63;
|
||||
|
||||
|
||||
// Interpolate the lowest floor:
|
||||
for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
|
||||
{
|
||||
@@ -428,7 +428,7 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
256;
|
||||
} // for x, z - FloorLo[]
|
||||
LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo);
|
||||
|
||||
|
||||
// Interpolate segments:
|
||||
for (int Segment = BaseY; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
|
||||
{
|
||||
@@ -441,12 +441,12 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
);
|
||||
} // for x, z - FloorLo[]
|
||||
LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi);
|
||||
|
||||
|
||||
// Interpolate between FloorLo and FloorHi:
|
||||
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
||||
{
|
||||
EMCSBiome biome = a_ChunkDesc.GetBiome(x, z);
|
||||
|
||||
|
||||
if ((biome == biExtremeHills) || (biome == biExtremeHillsEdge))
|
||||
{
|
||||
int Lo = FloorLo[x + 17 * z] / 256;
|
||||
@@ -462,7 +462,7 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
break;
|
||||
} // if (biome)
|
||||
} // for z, x
|
||||
|
||||
|
||||
// Swap the floors:
|
||||
std::swap(FloorLo, FloorHi);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
m_ShapeGen(a_ShapeGen),
|
||||
m_CompositionGen(a_CompositionGen)
|
||||
{}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int m_Seed;
|
||||
@@ -39,7 +39,7 @@ protected:
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
cTerrainShapeGenPtr m_ShapeGen;
|
||||
cTerrainCompositionGenPtr m_CompositionGen;
|
||||
|
||||
|
||||
/** Generates and applies an image of a single tree.
|
||||
Parts of the tree inside the chunk are applied to a_ChunkDesc.
|
||||
Parts of the tree outside the chunk are stored in a_OutsideXYZ
|
||||
@@ -50,7 +50,7 @@ protected:
|
||||
sSetBlockVector & a_OutsideLogs,
|
||||
sSetBlockVector & a_OutsideOther
|
||||
) ;
|
||||
|
||||
|
||||
/** Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow. */
|
||||
void ApplyTreeImage(
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
@@ -63,7 +63,7 @@ protected:
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
const cChunkDef::BiomeMap & a_Biomes
|
||||
);
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
} ;
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
m_Probability(a_Probability)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
cNoise m_Noise;
|
||||
int m_Seed;
|
||||
@@ -93,11 +93,11 @@ protected:
|
||||
|
||||
/** Chance, [0 .. 100], of a chunk having the lake. */
|
||||
int m_Probability;
|
||||
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
|
||||
/** Creates a lake image for the specified chunk into a_Lake. */
|
||||
void CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea & a_Lake);
|
||||
} ;
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
protected:
|
||||
cNoise m_Noise1;
|
||||
cNoise m_Noise2;
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
@@ -138,7 +138,7 @@ protected:
|
||||
cNoise m_NoiseY;
|
||||
cNoise m_NoiseZ;
|
||||
cNoise m_NoiseH;
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
} ;
|
||||
|
||||
@@ -171,7 +171,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case biTaiga:
|
||||
case biIcePlains:
|
||||
case biIceMountains:
|
||||
@@ -181,7 +181,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
GetConiferTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case biSwamplandM:
|
||||
case biSwampland:
|
||||
{
|
||||
@@ -189,7 +189,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
GetSwampTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case biJungle:
|
||||
case biJungleHills:
|
||||
case biJungleEdge:
|
||||
@@ -206,7 +206,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case biBirchForest:
|
||||
case biBirchForestHills:
|
||||
{
|
||||
@@ -259,7 +259,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
GetDarkoakTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case biMesa:
|
||||
case biMesaPlateauF:
|
||||
case biMesaPlateau:
|
||||
@@ -288,7 +288,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ASSERT(!"Invalid biome type!");
|
||||
}
|
||||
|
||||
@@ -320,24 +320,24 @@ void GetSmallAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a
|
||||
- 2 layers of BigO2 + random corners (log)
|
||||
- 1 to 3 blocks of trunk
|
||||
*/
|
||||
|
||||
|
||||
int Random = a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ) >> 3;
|
||||
|
||||
|
||||
HEIGHTTYPE Heights[] = {1, 2, 2, 3} ;
|
||||
HEIGHTTYPE Height = 1 + Heights[Random & 3];
|
||||
Random >>= 2;
|
||||
|
||||
|
||||
// Pre-alloc so that we don't realloc too often later:
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height + 5));
|
||||
a_OtherBlocks.reserve(ARRAYCOUNT(BigO2) * 2 + ARRAYCOUNT(BigO1) + ARRAYCOUNT(Corners) * 3 + 3 + 5);
|
||||
|
||||
|
||||
// Trunk:
|
||||
for (int i = 0; i < Height; i++)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_APPLE));
|
||||
}
|
||||
int Hei = a_BlockY + Height;
|
||||
|
||||
|
||||
// 2 BigO2 + corners layers:
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -346,7 +346,7 @@ void GetSmallAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, Hei, a_BlockZ, E_BLOCK_LOG, E_META_LOG_APPLE));
|
||||
Hei++;
|
||||
} // for i - 2*
|
||||
|
||||
|
||||
// Optional BigO1 + corners layer:
|
||||
if ((Random & 1) == 0)
|
||||
{
|
||||
@@ -355,7 +355,7 @@ void GetSmallAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, Hei, a_BlockZ, E_BLOCK_LOG, E_META_LOG_APPLE));
|
||||
Hei++;
|
||||
}
|
||||
|
||||
|
||||
// Top plus:
|
||||
PushCoordBlocks(a_BlockX, Hei, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE);
|
||||
a_OtherBlocks.push_back(sSetBlock(a_BlockX, Hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_APPLE));
|
||||
@@ -479,28 +479,28 @@ NIBBLETYPE GetLogMetaFromDirection(NIBBLETYPE a_BlockMeta, Vector3d a_Direction)
|
||||
void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
|
||||
{
|
||||
HEIGHTTYPE Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ) % 3);
|
||||
|
||||
|
||||
// Prealloc, so that we don't realloc too often later:
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height));
|
||||
a_OtherBlocks.reserve(80);
|
||||
|
||||
|
||||
// The entire trunk, out of logs:
|
||||
for (int i = Height - 1; i >= 0; --i)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_BIRCH));
|
||||
}
|
||||
int h = a_BlockY + Height;
|
||||
|
||||
|
||||
// Top layer - just the Plus:
|
||||
PushCoordBlocks(a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
|
||||
a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH)); // There's no log at this layer
|
||||
h--;
|
||||
|
||||
|
||||
// Second layer - log, Plus and maybe Corners:
|
||||
PushCoordBlocks (a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
|
||||
PushCornerBlocks(a_BlockX, h, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
|
||||
h--;
|
||||
|
||||
|
||||
// Third and fourth layers - BigO2 and maybe 2 * Corners:
|
||||
for (int Row = 0; Row < 2; Row++)
|
||||
{
|
||||
@@ -518,7 +518,7 @@ void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
|
||||
{
|
||||
// Calculate a base height
|
||||
int Height = 2 + (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 11 % 3);
|
||||
|
||||
|
||||
// Create the trunk
|
||||
for (int i = 0; i < Height; i++)
|
||||
{
|
||||
@@ -653,28 +653,28 @@ void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
|
||||
{
|
||||
HEIGHTTYPE Height = 9 + (a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ) % 3);
|
||||
|
||||
|
||||
// Prealloc, so that we don't realloc too often later:
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height));
|
||||
a_OtherBlocks.reserve(80);
|
||||
|
||||
|
||||
// The entire trunk, out of logs:
|
||||
for (int i = Height - 1; i >= 0; --i)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_BIRCH));
|
||||
}
|
||||
int h = a_BlockY + Height;
|
||||
|
||||
|
||||
// Top layer - just the Plus:
|
||||
PushCoordBlocks(a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
|
||||
a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH)); // There's no log at this layer
|
||||
h--;
|
||||
|
||||
|
||||
// Second layer - log, Plus and maybe Corners:
|
||||
PushCoordBlocks (a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
|
||||
PushCornerBlocks(a_BlockX, h, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH);
|
||||
h--;
|
||||
|
||||
|
||||
// Third and fourth layers - BigO2 and maybe 2 * Corners:
|
||||
for (int Row = 0; Row < 2; Row++)
|
||||
{
|
||||
@@ -710,11 +710,11 @@ void GetSpruceTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
|
||||
// Spruces have a top section with layer sizes of (0, 1, 0) or only (1, 0),
|
||||
// then 1 - 3 sections of ascending sizes (1, 2) [most often], (1, 3) or (1, 2, 3)
|
||||
// and an optional bottom section of size 1, followed by 1 - 3 clear trunk blocks
|
||||
|
||||
|
||||
// We'll use bits from this number as partial random numbers; but the noise function has mod8 irregularities
|
||||
// (each of the mod8 remainders has a very different chance of occurrence) - that's why we divide by 8
|
||||
int MyRandom = a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY + 32 * a_Seq, a_BlockZ) / 8;
|
||||
|
||||
|
||||
static const HEIGHTTYPE sHeights[] = {1, 2, 2, 3};
|
||||
HEIGHTTYPE Height = sHeights[MyRandom & 3];
|
||||
MyRandom >>= 2;
|
||||
@@ -722,14 +722,14 @@ void GetSpruceTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
|
||||
// Prealloc, so that we don't realloc too often later:
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height));
|
||||
a_OtherBlocks.reserve(180);
|
||||
|
||||
|
||||
// Clear trunk blocks:
|
||||
for (int i = 0; i < Height; i++)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER));
|
||||
}
|
||||
Height += a_BlockY;
|
||||
|
||||
|
||||
// Optional size-1 bottom leaves layer:
|
||||
if ((MyRandom & 1) == 0)
|
||||
{
|
||||
@@ -738,7 +738,7 @@ void GetSpruceTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
|
||||
Height++;
|
||||
}
|
||||
MyRandom >>= 1;
|
||||
|
||||
|
||||
// 1 to 3 sections of leaves layers:
|
||||
static const int sNumSections[] = {1, 2, 2, 3};
|
||||
int NumSections = sNumSections[MyRandom & 3];
|
||||
@@ -780,7 +780,7 @@ void GetSpruceTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
|
||||
} // switch (SectionType)
|
||||
MyRandom >>= 2;
|
||||
} // for i - Sections
|
||||
|
||||
|
||||
if ((MyRandom & 1) == 0)
|
||||
{
|
||||
// (0, 1, 0) top:
|
||||
@@ -806,7 +806,7 @@ void GetPineTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise
|
||||
{
|
||||
// Tall, little leaves on top. The top leaves are arranged in a shape of two cones joined by their bases.
|
||||
// There can be one or two layers representing the cone bases (SameSizeMax)
|
||||
|
||||
|
||||
int MyRandom = a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 8;
|
||||
int TrunkHeight = 8 + (MyRandom % 3);
|
||||
int SameSizeMax = ((MyRandom & 8) == 0) ? 1 : 0;
|
||||
@@ -816,7 +816,7 @@ void GetPineTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise
|
||||
{
|
||||
SameSizeMax = 0;
|
||||
}
|
||||
|
||||
|
||||
// Pre-allocate the vector:
|
||||
a_LogBlocks.reserve(static_cast<size_t>(TrunkHeight));
|
||||
a_OtherBlocks.reserve(static_cast<size_t>(NumLeavesLayers * 25));
|
||||
@@ -867,19 +867,19 @@ void GetSwampTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
|
||||
} ;
|
||||
|
||||
int Height = 3 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 8) % 3;
|
||||
|
||||
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height));
|
||||
a_OtherBlocks.reserve(2 * ARRAYCOUNT(BigO2) + 2 * ARRAYCOUNT(BigO3) + static_cast<size_t>(Height) * ARRAYCOUNT(Vines) + 20);
|
||||
|
||||
|
||||
for (int i = 0; i < Height; i++)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_APPLE));
|
||||
}
|
||||
int hei = a_BlockY + Height - 2;
|
||||
|
||||
|
||||
// Put vines around the lowermost leaves layer:
|
||||
PushSomeColumns(a_BlockX, hei, a_BlockZ, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES);
|
||||
|
||||
|
||||
// The lower two leaves layers are BigO3 with log in the middle and possibly corners:
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -905,16 +905,16 @@ void GetSwampTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
|
||||
void GetAppleBushImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
|
||||
{
|
||||
a_OtherBlocks.reserve(3 + ARRAYCOUNT(BigO2) + ARRAYCOUNT(BigO1));
|
||||
|
||||
|
||||
int hei = a_BlockY;
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LOG, E_META_LOG_JUNGLE));
|
||||
PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE);
|
||||
hei++;
|
||||
|
||||
|
||||
a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_APPLE));
|
||||
PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE);
|
||||
hei++;
|
||||
|
||||
|
||||
a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_APPLE));
|
||||
}
|
||||
|
||||
@@ -951,12 +951,12 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
{-5, -2, 8}, {-5, -1, 8}, {-5, 0, 8}, {-5, 1, 8}, {-5, 2, 8}, // West face
|
||||
// TODO: vines around the trunk, proper metas and height
|
||||
} ;
|
||||
|
||||
|
||||
int Height = 24 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 24;
|
||||
|
||||
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height) * 4);
|
||||
a_OtherBlocks.reserve(2 * ARRAYCOUNT(BigO4) + ARRAYCOUNT(BigO3) + static_cast<size_t>(Height) * ARRAYCOUNT(Vines) + 50);
|
||||
|
||||
|
||||
for (int i = 0; i < Height; i++)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_JUNGLE));
|
||||
@@ -965,10 +965,10 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_LOG, E_META_LOG_JUNGLE));
|
||||
}
|
||||
int hei = a_BlockY + Height - 2;
|
||||
|
||||
|
||||
// Put vines around the lowermost leaves layer:
|
||||
PushSomeColumns(a_BlockX, hei, a_BlockZ, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES);
|
||||
|
||||
|
||||
// The lower two leaves layers are BigO4 with log in the middle and possibly corners:
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -1000,7 +1000,7 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
} ;
|
||||
|
||||
int Height = 7 + (a_Noise.IntNoise3DInt(a_BlockX + 5 * a_Seq, a_BlockY, a_BlockZ + 5 * a_Seq) / 5) % 3;
|
||||
|
||||
|
||||
a_LogBlocks.reserve(static_cast<size_t>(Height));
|
||||
a_OtherBlocks.reserve(
|
||||
2 * ARRAYCOUNT(BigO3) + // O3 layer, 2x
|
||||
@@ -1009,16 +1009,16 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
static_cast<size_t>(Height) * ARRAYCOUNT(Vines) + // Vines
|
||||
50 // some safety
|
||||
);
|
||||
|
||||
|
||||
for (int i = 0; i < Height; i++)
|
||||
{
|
||||
a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_JUNGLE));
|
||||
}
|
||||
int hei = a_BlockY + Height - 3;
|
||||
|
||||
|
||||
// Put vines around the lowermost leaves layer:
|
||||
PushSomeColumns(a_BlockX, hei, a_BlockZ, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES);
|
||||
|
||||
|
||||
// The lower two leaves layers are BigO3 with log in the middle and possibly corners:
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -1034,7 +1034,7 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE);
|
||||
hei++;
|
||||
} // for i - 2*
|
||||
|
||||
|
||||
// Top plus, all leaves:
|
||||
PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE);
|
||||
a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE));
|
||||
|
||||
@@ -67,14 +67,14 @@ public:
|
||||
RoadPiece->AddConnector(0, 0, 1, BLOCK_FACE_XM, -2);
|
||||
RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2);
|
||||
RoadPiece->SetDefaultWeight(100);
|
||||
|
||||
|
||||
// Add the road connectors:
|
||||
for (int x = 1; x < len; x += 12)
|
||||
{
|
||||
RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 2);
|
||||
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 2);
|
||||
}
|
||||
|
||||
|
||||
// Add the buildings connectors:
|
||||
for (int x = 7; x < len; x += 12)
|
||||
{
|
||||
@@ -87,8 +87,8 @@ public:
|
||||
m_PiecesByConnector[2].push_back(RoadPiece);
|
||||
} // for len - roads of varying length
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// cPrefabPiecePool overrides:
|
||||
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override
|
||||
{
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return static_cast<const cPrefab &>(a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
|
||||
}
|
||||
};
|
||||
@@ -111,7 +111,7 @@ class cVillageGen::cVillage :
|
||||
protected cPiecePool
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
|
||||
public:
|
||||
cVillage(
|
||||
int a_Seed,
|
||||
@@ -140,38 +140,38 @@ public:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~cVillage()
|
||||
{
|
||||
cPieceGenerator::FreePieces(m_Pieces);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
/** Seed for the random functions */
|
||||
int m_Seed;
|
||||
|
||||
|
||||
/** The noise used as a pseudo-random generator */
|
||||
cNoise m_Noise;
|
||||
|
||||
|
||||
/** Maximum size, in X / Z blocks, of the village (radius from the origin) */
|
||||
int m_MaxSize;
|
||||
|
||||
|
||||
/** The density for this village. Used to refrain from populating all house connectors. Range [0, 100] */
|
||||
int m_Density;
|
||||
|
||||
|
||||
/** Borders of the village - no item may reach out of this cuboid. */
|
||||
cCuboid m_Borders;
|
||||
|
||||
|
||||
/** Prefabs to use for buildings */
|
||||
cVillagePiecePool & m_Prefabs;
|
||||
|
||||
|
||||
/** The underlying height generator, used for placing the structures on top of the terrain. */
|
||||
cTerrainHeightGenPtr m_HeightGen;
|
||||
|
||||
|
||||
/** The village pieces, placed by the generator. */
|
||||
cPlacedPieces m_Pieces;
|
||||
|
||||
|
||||
|
||||
|
||||
// cGridStructGen::cStructure overrides:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
|
||||
{
|
||||
@@ -213,8 +213,8 @@ protected:
|
||||
int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ);
|
||||
a_Piece.MoveToGroundBy(TerrainHeight - FirstConnector.m_Pos.y + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Draws the road into the chunk.
|
||||
The heightmap is not queried from the heightgen, but is given via parameter, so that it may be queried just
|
||||
once for all roads in a chunk. */
|
||||
@@ -245,21 +245,21 @@ protected:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// cPiecePool overrides:
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override
|
||||
{
|
||||
return m_Prefabs.GetPiecesWithConnector(a_ConnectorType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cPieces GetStartingPieces(void) override
|
||||
{
|
||||
return m_Prefabs.GetStartingPieces();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual int GetPieceWeight(
|
||||
const cPlacedPiece & a_PlacedPiece,
|
||||
const cPiece::cConnector & a_ExistingConnector,
|
||||
@@ -276,30 +276,30 @@ protected:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Density check passed, relay to m_Prefabs:
|
||||
return m_Prefabs.GetPieceWeight(a_PlacedPiece, a_ExistingConnector, a_NewPiece);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual int GetStartingPieceWeight(const cPiece & a_NewPiece) override
|
||||
{
|
||||
return m_Prefabs.GetStartingPieceWeight(a_NewPiece);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) override
|
||||
{
|
||||
m_Prefabs.PiecePlaced(a_Piece);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void Reset(void) override
|
||||
{
|
||||
m_Prefabs.Reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MoveAllDescendants(cPlacedPieces & a_PlacedPieces, size_t a_Pivot, int a_HeightDifference)
|
||||
{
|
||||
size_t num = a_PlacedPieces.size();
|
||||
@@ -416,7 +416,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_GridX, int a_Gr
|
||||
{
|
||||
Density = pool->GetMinDensity();
|
||||
}
|
||||
|
||||
|
||||
// Create a village based on the chosen prefabs:
|
||||
return cStructurePtr(new cVillage(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *pool.get(), m_HeightGen));
|
||||
}
|
||||
|
||||
@@ -48,22 +48,22 @@ protected:
|
||||
|
||||
/** The noise used for generating random numbers */
|
||||
cNoise m_Noise;
|
||||
|
||||
|
||||
/** Maximum depth of the generator tree */
|
||||
int m_MaxDepth;
|
||||
|
||||
|
||||
/** Maximum size, in X / Z blocks, of the village (radius from the origin) */
|
||||
int m_MaxSize;
|
||||
|
||||
|
||||
/** Minimum density - percentage of allowed house connections. Range [0, 100] */
|
||||
int m_MinDensity;
|
||||
|
||||
|
||||
/** Maximum density - percentage of allowed house connections. Range [0, 100] */
|
||||
int m_MaxDensity;
|
||||
|
||||
/** The underlying biome generator that defines whether the village is created or not */
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
|
||||
|
||||
/** The underlying height generator, used to position the prefabs crossing chunk borders */
|
||||
cTerrainHeightGenPtr m_HeightGen;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user