DistortedHeightmap: Improved speed, prepared for mesa biomes.
This generates the rainbow-mesa as seen on the first mesa screenshot in the forum.
This commit is contained in:
parent
3963a72046
commit
9b881a15ef
@ -14,6 +14,141 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cPattern:
|
||||||
|
|
||||||
|
/// This class is used to store a column pattern initialized at runtime,
|
||||||
|
/// so that the program doesn't need to explicitly set 256 values for each pattern
|
||||||
|
/// Each pattern has 256 blocks so that there's no need to check pattern bounds when assigning the
|
||||||
|
/// pattern - there will always be enough pattern left, even for the whole chunk height
|
||||||
|
class cPattern
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cPattern(cDistortedHeightmap::sBlockInfo * a_TopBlocks, size_t a_Count)
|
||||||
|
{
|
||||||
|
// Copy the pattern into the top:
|
||||||
|
for (size_t i = 0; i < a_Count; i++)
|
||||||
|
{
|
||||||
|
m_Pattern[i] = a_TopBlocks[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the rest with stone:
|
||||||
|
static cDistortedHeightmap::sBlockInfo Stone = {E_BLOCK_STONE, 0};
|
||||||
|
for (size_t i = a_Count; i < cChunkDef::Height; i++)
|
||||||
|
{
|
||||||
|
m_Pattern[i] = Stone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cDistortedHeightmap::sBlockInfo * Get(void) const { return m_Pattern; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cDistortedHeightmap::sBlockInfo m_Pattern[cChunkDef::Height];
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The arrays to use for the top block pattern definitions:
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbGrass[] =
|
||||||
|
{
|
||||||
|
{E_BLOCK_GRASS, 0},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbSand[] =
|
||||||
|
{
|
||||||
|
{ E_BLOCK_SAND, 0},
|
||||||
|
{ E_BLOCK_SAND, 0},
|
||||||
|
{ E_BLOCK_SAND, 0},
|
||||||
|
{ E_BLOCK_SANDSTONE, 0},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbDirt[] =
|
||||||
|
{
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbPodzol[] =
|
||||||
|
{
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_PODZOL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbGrassLess[] =
|
||||||
|
{
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_GRASSLESS},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
{E_BLOCK_DIRT, E_META_DIRT_NORMAL},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbMycelium[] =
|
||||||
|
{
|
||||||
|
{E_BLOCK_MYCELIUM, 0},
|
||||||
|
{E_BLOCK_DIRT, 0},
|
||||||
|
{E_BLOCK_DIRT, 0},
|
||||||
|
{E_BLOCK_DIRT, 0},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Ocean floor pattern top-block definitions:
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbOFSand[] =
|
||||||
|
{
|
||||||
|
{E_BLOCK_SAND, 0},
|
||||||
|
{E_BLOCK_SAND, 0},
|
||||||
|
{E_BLOCK_SAND, 0},
|
||||||
|
{E_BLOCK_SANDSTONE, 0}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static cDistortedHeightmap::sBlockInfo tbOFClay[] =
|
||||||
|
{
|
||||||
|
{ E_BLOCK_CLAY, 0},
|
||||||
|
{ E_BLOCK_CLAY, 0},
|
||||||
|
{ E_BLOCK_SAND, 0},
|
||||||
|
{ E_BLOCK_SAND, 0},
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Individual patterns to use:
|
||||||
|
|
||||||
|
static cPattern patGrass (tbGrass, ARRAYCOUNT(tbGrass));
|
||||||
|
static cPattern patSand (tbSand, ARRAYCOUNT(tbSand));
|
||||||
|
static cPattern patDirt (tbDirt, ARRAYCOUNT(tbDirt));
|
||||||
|
static cPattern patPodzol (tbPodzol, ARRAYCOUNT(tbPodzol));
|
||||||
|
static cPattern patGrassLess(tbGrassLess, ARRAYCOUNT(tbGrassLess));
|
||||||
|
static cPattern patMycelium (tbMycelium, ARRAYCOUNT(tbMycelium));
|
||||||
|
|
||||||
|
static cPattern patOFSand (tbOFSand, ARRAYCOUNT(tbOFSand));
|
||||||
|
static cPattern patOFClay (tbOFClay, ARRAYCOUNT(tbOFClay));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cDistortedHeightmap:
|
||||||
|
|
||||||
/** This table assigns a relative maximum overhang size in each direction to biomes.
|
/** This table assigns a relative maximum overhang size in each direction to biomes.
|
||||||
Both numbers indicate a number which will multiply the noise value for each coord;
|
Both numbers indicate a number which will multiply the noise value for each coord;
|
||||||
this means that you can have different-sized overhangs in each direction.
|
this means that you can have different-sized overhangs in each direction.
|
||||||
@ -120,6 +255,7 @@ cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen) :
|
|||||||
m_NoiseDistortX(a_Seed + 1000),
|
m_NoiseDistortX(a_Seed + 1000),
|
||||||
m_NoiseDistortZ(a_Seed + 2000),
|
m_NoiseDistortZ(a_Seed + 2000),
|
||||||
m_OceanFloorSelect(a_Seed + 3000),
|
m_OceanFloorSelect(a_Seed + 3000),
|
||||||
|
m_MesaFloor(a_Seed + 4000),
|
||||||
m_BiomeGen(a_BiomeGen),
|
m_BiomeGen(a_BiomeGen),
|
||||||
m_UnderlyingHeiGen(a_Seed, a_BiomeGen),
|
m_UnderlyingHeiGen(a_Seed, a_BiomeGen),
|
||||||
m_HeightGen(m_UnderlyingHeiGen, 64),
|
m_HeightGen(m_UnderlyingHeiGen, 64),
|
||||||
@ -132,6 +268,18 @@ cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen) :
|
|||||||
m_NoiseDistortZ.AddOctave((NOISE_DATATYPE)1, (NOISE_DATATYPE)0.5);
|
m_NoiseDistortZ.AddOctave((NOISE_DATATYPE)1, (NOISE_DATATYPE)0.5);
|
||||||
m_NoiseDistortZ.AddOctave((NOISE_DATATYPE)0.5, (NOISE_DATATYPE)1);
|
m_NoiseDistortZ.AddOctave((NOISE_DATATYPE)0.5, (NOISE_DATATYPE)1);
|
||||||
m_NoiseDistortZ.AddOctave((NOISE_DATATYPE)0.25, (NOISE_DATATYPE)2);
|
m_NoiseDistortZ.AddOctave((NOISE_DATATYPE)0.25, (NOISE_DATATYPE)2);
|
||||||
|
|
||||||
|
// TODO: Initialize the mesa pattern with a random selection of clay layers:
|
||||||
|
for (int i = 0; i < cChunkDef::Height; i++)
|
||||||
|
{
|
||||||
|
m_MesaPattern[i].BlockMeta = i % 16;
|
||||||
|
m_MesaPattern[i].BlockType = E_BLOCK_STAINED_CLAY;
|
||||||
|
}
|
||||||
|
for (int i = cChunkDef::Height; i < 2 * cChunkDef::Height; i++)
|
||||||
|
{
|
||||||
|
m_MesaPattern[i].BlockMeta = 0;
|
||||||
|
m_MesaPattern[i].BlockType = E_BLOCK_STONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -265,10 +413,6 @@ void cDistortedHeightmap::InitializeHeightGen(cIniFile & a_IniFile)
|
|||||||
|
|
||||||
void cDistortedHeightmap::ComposeTerrain(cChunkDesc & a_ChunkDesc)
|
void cDistortedHeightmap::ComposeTerrain(cChunkDesc & a_ChunkDesc)
|
||||||
{
|
{
|
||||||
// Frequencies for the ocean floor selecting noise:
|
|
||||||
NOISE_DATATYPE FrequencyX = 3;
|
|
||||||
NOISE_DATATYPE FrequencyZ = 3;
|
|
||||||
|
|
||||||
// Prepare the internal state for generating this chunk:
|
// Prepare the internal state for generating this chunk:
|
||||||
PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ());
|
PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ());
|
||||||
|
|
||||||
@ -278,159 +422,7 @@ void cDistortedHeightmap::ComposeTerrain(cChunkDesc & a_ChunkDesc)
|
|||||||
{
|
{
|
||||||
for (int x = 0; x < cChunkDef::Width; x++)
|
for (int x = 0; x < cChunkDef::Width; x++)
|
||||||
{
|
{
|
||||||
int NoiseArrayIdx = x + 17 * 257 * z;
|
ComposeColumn(a_ChunkDesc, x, z);
|
||||||
int LastAir = a_ChunkDesc.GetHeight(x, z) + 1;
|
|
||||||
bool HasHadWater = false;
|
|
||||||
for (int y = LastAir - 1; y > 0; y--)
|
|
||||||
{
|
|
||||||
int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y];
|
|
||||||
|
|
||||||
if (y >= HeightMapHeight)
|
|
||||||
{
|
|
||||||
// "air" part
|
|
||||||
LastAir = y;
|
|
||||||
if (y < m_SeaLevel)
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER);
|
|
||||||
HasHadWater = true;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// "ground" part:
|
|
||||||
if (y < LastAir - 4)
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (HasHadWater)
|
|
||||||
{
|
|
||||||
// Decide between clay, sand and dirt
|
|
||||||
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + x)) / FrequencyX;
|
|
||||||
NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + z)) / FrequencyZ;
|
|
||||||
NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY);
|
|
||||||
if (Val < -0.95)
|
|
||||||
{
|
|
||||||
// Clay:
|
|
||||||
switch (LastAir - y)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_CLAY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SANDSTONE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // switch (floor depth)
|
|
||||||
}
|
|
||||||
else if (Val < 0)
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, (y < LastAir - 3) ? E_BLOCK_SANDSTONE : E_BLOCK_SAND);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_DIRT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (a_ChunkDesc.GetBiome(x, z))
|
|
||||||
{
|
|
||||||
case biOcean:
|
|
||||||
case biPlains:
|
|
||||||
case biExtremeHills:
|
|
||||||
case biForest:
|
|
||||||
case biTaiga:
|
|
||||||
case biSwampland:
|
|
||||||
case biRiver:
|
|
||||||
case biFrozenOcean:
|
|
||||||
case biFrozenRiver:
|
|
||||||
case biIcePlains:
|
|
||||||
case biIceMountains:
|
|
||||||
case biForestHills:
|
|
||||||
case biTaigaHills:
|
|
||||||
case biExtremeHillsEdge:
|
|
||||||
case biJungle:
|
|
||||||
case biJungleHills:
|
|
||||||
case biJungleEdge:
|
|
||||||
case biDeepOcean:
|
|
||||||
case biStoneBeach:
|
|
||||||
case biColdBeach:
|
|
||||||
case biBirchForest:
|
|
||||||
case biBirchForestHills:
|
|
||||||
case biRoofedForest:
|
|
||||||
case biColdTaiga:
|
|
||||||
case biColdTaigaHills:
|
|
||||||
case biExtremeHillsPlus:
|
|
||||||
case biSavanna:
|
|
||||||
case biSavannaPlateau:
|
|
||||||
case biSunflowerPlains:
|
|
||||||
case biExtremeHillsM:
|
|
||||||
case biFlowerForest:
|
|
||||||
case biTaigaM:
|
|
||||||
case biSwamplandM:
|
|
||||||
case biIcePlainsSpikes:
|
|
||||||
case biJungleM:
|
|
||||||
case biJungleEdgeM:
|
|
||||||
case biBirchForestM:
|
|
||||||
case biBirchForestHillsM:
|
|
||||||
case biRoofedForestM:
|
|
||||||
case biColdTaigaM:
|
|
||||||
case biExtremeHillsPlusM:
|
|
||||||
case biSavannaM:
|
|
||||||
case biSavannaPlateauM:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, (y == LastAir - 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case biMesa:
|
|
||||||
case biMesaPlateauF:
|
|
||||||
case biMesaPlateau:
|
|
||||||
case biMesaBryce:
|
|
||||||
case biMesaPlateauFM:
|
|
||||||
case biMesaPlateauM:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_HARDENED_CLAY, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case biMegaTaiga:
|
|
||||||
case biMegaTaigaHills:
|
|
||||||
case biMegaSpruceTaiga:
|
|
||||||
case biMegaSpruceTaigaHills:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_DIRT, (y == LastAir - 1) ? E_META_DIRT_PODZOL : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case biDesertHills:
|
|
||||||
case biDesert:
|
|
||||||
case biDesertM:
|
|
||||||
case biBeach:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, (y < LastAir - 3) ? E_BLOCK_SANDSTONE : E_BLOCK_SAND);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case biMushroomIsland:
|
|
||||||
case biMushroomShore:
|
|
||||||
{
|
|
||||||
a_ChunkDesc.SetBlockType(x, y, z, (y == LastAir - 1) ? E_BLOCK_MYCELIUM : E_BLOCK_DIRT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // for y
|
|
||||||
a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK);
|
|
||||||
} // for x
|
} // for x
|
||||||
} // for z
|
} // for z
|
||||||
}
|
}
|
||||||
@ -563,3 +555,253 @@ void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_R
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cDistortedHeightmap::ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ)
|
||||||
|
{
|
||||||
|
EMCSBiome Biome = a_ChunkDesc.GetBiome(a_RelX, a_RelZ);
|
||||||
|
switch (Biome)
|
||||||
|
{
|
||||||
|
case biOcean:
|
||||||
|
case biPlains:
|
||||||
|
case biExtremeHills:
|
||||||
|
case biForest:
|
||||||
|
case biTaiga:
|
||||||
|
case biSwampland:
|
||||||
|
case biRiver:
|
||||||
|
case biFrozenOcean:
|
||||||
|
case biFrozenRiver:
|
||||||
|
case biIcePlains:
|
||||||
|
case biIceMountains:
|
||||||
|
case biForestHills:
|
||||||
|
case biTaigaHills:
|
||||||
|
case biExtremeHillsEdge:
|
||||||
|
case biJungle:
|
||||||
|
case biJungleHills:
|
||||||
|
case biJungleEdge:
|
||||||
|
case biDeepOcean:
|
||||||
|
case biStoneBeach:
|
||||||
|
case biColdBeach:
|
||||||
|
case biBirchForest:
|
||||||
|
case biBirchForestHills:
|
||||||
|
case biRoofedForest:
|
||||||
|
case biColdTaiga:
|
||||||
|
case biColdTaigaHills:
|
||||||
|
case biExtremeHillsPlus:
|
||||||
|
case biSavanna:
|
||||||
|
case biSavannaPlateau:
|
||||||
|
case biSunflowerPlains:
|
||||||
|
case biExtremeHillsM:
|
||||||
|
case biFlowerForest:
|
||||||
|
case biTaigaM:
|
||||||
|
case biSwamplandM:
|
||||||
|
case biIcePlainsSpikes:
|
||||||
|
case biJungleM:
|
||||||
|
case biJungleEdgeM:
|
||||||
|
case biBirchForestM:
|
||||||
|
case biBirchForestHillsM:
|
||||||
|
case biRoofedForestM:
|
||||||
|
case biColdTaigaM:
|
||||||
|
case biExtremeHillsPlusM:
|
||||||
|
case biSavannaM:
|
||||||
|
case biSavannaPlateauM:
|
||||||
|
{
|
||||||
|
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patGrass.Get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case biMegaTaiga:
|
||||||
|
case biMegaTaigaHills:
|
||||||
|
case biMegaSpruceTaiga:
|
||||||
|
case biMegaSpruceTaigaHills:
|
||||||
|
{
|
||||||
|
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patPodzol.Get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case biDesertHills:
|
||||||
|
case biDesert:
|
||||||
|
case biDesertM:
|
||||||
|
case biBeach:
|
||||||
|
{
|
||||||
|
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patSand.Get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case biMushroomIsland:
|
||||||
|
case biMushroomShore:
|
||||||
|
{
|
||||||
|
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patMycelium.Get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case biMesa:
|
||||||
|
case biMesaPlateauF:
|
||||||
|
case biMesaPlateau:
|
||||||
|
case biMesaBryce:
|
||||||
|
case biMesaPlateauFM:
|
||||||
|
case biMesaPlateauM:
|
||||||
|
{
|
||||||
|
// Mesa biomes need special handling, because they don't follow the usual "4 blocks from top pattern",
|
||||||
|
// instead, they provide a "from bottom" pattern with varying base height,
|
||||||
|
// usually 4 blocks below the ocean level
|
||||||
|
FillColumnMesa(a_ChunkDesc, a_RelX, a_RelZ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // switch (Biome)
|
||||||
|
ASSERT(!"Unhandled biome");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cDistortedHeightmap::FillColumnPattern(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const sBlockInfo * a_Pattern)
|
||||||
|
{
|
||||||
|
int NoiseArrayIdx = a_RelX + 17 * 257 * a_RelZ;
|
||||||
|
bool HasHadWater = false;
|
||||||
|
int PatternIdx = 0;
|
||||||
|
for (int y = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); y > 0; y--)
|
||||||
|
{
|
||||||
|
int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y];
|
||||||
|
|
||||||
|
if (y < HeightMapHeight)
|
||||||
|
{
|
||||||
|
// "ground" part, use the pattern:
|
||||||
|
a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[PatternIdx].BlockType, a_Pattern[PatternIdx].BlockMeta);
|
||||||
|
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:
|
||||||
|
a_Pattern = ChooseOceanFloorPattern(a_RelX, a_RelZ);
|
||||||
|
HasHadWater = true;
|
||||||
|
} // for y
|
||||||
|
a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cDistortedHeightmap::FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ)
|
||||||
|
{
|
||||||
|
// Frequencies for the clay floor noise:
|
||||||
|
const NOISE_DATATYPE FrequencyX = 50;
|
||||||
|
const NOISE_DATATYPE FrequencyZ = 50;
|
||||||
|
|
||||||
|
int Top = a_ChunkDesc.GetHeight(a_RelX, a_RelZ);
|
||||||
|
if (Top < m_SeaLevel)
|
||||||
|
{
|
||||||
|
// The terrain is below sealevel, handle as regular dirt terrain:
|
||||||
|
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patDirt.Get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + a_RelX)) / FrequencyX;
|
||||||
|
NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ;
|
||||||
|
int ClayFloor = m_SeaLevel - 6 + (int)(4.f * m_MesaFloor.CubicNoise2D(NoiseX, NoiseY));
|
||||||
|
if (ClayFloor >= Top)
|
||||||
|
{
|
||||||
|
ClayFloor = Top - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Top - ClayFloor < 5)
|
||||||
|
{
|
||||||
|
// Simple case: top is red sand, then hardened clay down to ClayFloor, then stone:
|
||||||
|
a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, E_BLOCK_SAND, E_META_SAND_RED);
|
||||||
|
for (int y = Top - 1; y >= ClayFloor; y--)
|
||||||
|
{
|
||||||
|
a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_HARDENED_CLAY);
|
||||||
|
}
|
||||||
|
for (int y = ClayFloor - 1; y > 0; y--)
|
||||||
|
{
|
||||||
|
a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE);
|
||||||
|
}
|
||||||
|
a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difficult case: use the mesa pattern and watch for overhangs:
|
||||||
|
int NoiseArrayIdx = a_RelX + 17 * 257 * a_RelZ;
|
||||||
|
int PatternIdx = cChunkDef::Height - (Top - ClayFloor); // We want the block at index ClayFloor to be pattern's 256th block (first stone)
|
||||||
|
const sBlockInfo * Pattern = m_MesaPattern;
|
||||||
|
bool HasHadWater = false;
|
||||||
|
for (int y = Top; y > 0; y--)
|
||||||
|
{
|
||||||
|
int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y];
|
||||||
|
if (y < HeightMapHeight)
|
||||||
|
{
|
||||||
|
// "ground" part, use the pattern:
|
||||||
|
a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, Pattern[PatternIdx].BlockType, Pattern[PatternIdx].BlockMeta);
|
||||||
|
PatternIdx++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y >= m_SeaLevel)
|
||||||
|
{
|
||||||
|
// "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);
|
||||||
|
if (HasHadWater)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select the ocean-floor pattern to use:
|
||||||
|
Pattern = ChooseOceanFloorPattern(a_RelX, a_RelZ);
|
||||||
|
HasHadWater = true;
|
||||||
|
} // for y
|
||||||
|
a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const cDistortedHeightmap::sBlockInfo * cDistortedHeightmap::ChooseOceanFloorPattern(int a_RelX, int a_RelZ)
|
||||||
|
{
|
||||||
|
// Frequencies for the ocean floor selecting noise:
|
||||||
|
const NOISE_DATATYPE FrequencyX = 3;
|
||||||
|
const NOISE_DATATYPE FrequencyZ = 3;
|
||||||
|
|
||||||
|
// Select the ocean-floor pattern to use:
|
||||||
|
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + a_RelX)) / FrequencyX;
|
||||||
|
NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ;
|
||||||
|
NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY);
|
||||||
|
if (Val < -0.95)
|
||||||
|
{
|
||||||
|
return patOFClay.Get();
|
||||||
|
}
|
||||||
|
else if (Val < 0)
|
||||||
|
{
|
||||||
|
return patOFSand.Get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return patDirt.Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,13 @@ class cDistortedHeightmap :
|
|||||||
public cTerrainCompositionGen
|
public cTerrainCompositionGen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// Structure used for storing block patterns for columns
|
||||||
|
struct sBlockInfo
|
||||||
|
{
|
||||||
|
BLOCKTYPE BlockType;
|
||||||
|
NIBBLETYPE BlockMeta;
|
||||||
|
} ;
|
||||||
|
|
||||||
cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen);
|
cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -46,6 +53,7 @@ protected:
|
|||||||
cPerlinNoise m_NoiseDistortX;
|
cPerlinNoise m_NoiseDistortX;
|
||||||
cPerlinNoise m_NoiseDistortZ;
|
cPerlinNoise m_NoiseDistortZ;
|
||||||
cNoise m_OceanFloorSelect; ///< Used for selecting between dirt and sand on the ocean floor
|
cNoise m_OceanFloorSelect; ///< Used for selecting between dirt and sand on the ocean floor
|
||||||
|
cNoise m_MesaFloor; ///< Used for the floor of the clay blocks in mesa biomes
|
||||||
|
|
||||||
int m_SeaLevel;
|
int m_SeaLevel;
|
||||||
NOISE_DATATYPE m_FrequencyX;
|
NOISE_DATATYPE m_FrequencyX;
|
||||||
@ -78,6 +86,10 @@ protected:
|
|||||||
/// True if Initialize() has been called. Used to initialize-once even with multiple init entrypoints (HeiGen / CompoGen)
|
/// True if Initialize() has been called. Used to initialize-once even with multiple init entrypoints (HeiGen / CompoGen)
|
||||||
bool m_IsInitialized;
|
bool m_IsInitialized;
|
||||||
|
|
||||||
|
/// The vertical pattern to be used for mesa biomes. Seed-dependant.
|
||||||
|
/// One Height of pattern and one Height of stone to avoid checking pattern dimensions
|
||||||
|
sBlockInfo m_MesaPattern[2 * cChunkDef::Height];
|
||||||
|
|
||||||
|
|
||||||
/// Unless the LastChunk coords are equal to coords given, prepares the internal state (noise arrays, heightmap)
|
/// Unless the LastChunk coords are equal to coords given, prepares the internal state (noise arrays, heightmap)
|
||||||
void PrepareState(int a_ChunkX, int a_ChunkZ);
|
void PrepareState(int a_ChunkX, int a_ChunkZ);
|
||||||
@ -97,6 +109,19 @@ protected:
|
|||||||
/// Reads the settings from the ini file. Skips reading if already initialized
|
/// Reads the settings from the ini file. Skips reading if already initialized
|
||||||
void Initialize(cIniFile & a_IniFile);
|
void Initialize(cIniFile & a_IniFile);
|
||||||
|
|
||||||
|
/// Composes a single column in a_ChunkDesc. Chooses what to do based on the biome in that column
|
||||||
|
void ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ);
|
||||||
|
|
||||||
|
/// Fills the specified column with the specified pattern; restarts the pattern when air is reached,
|
||||||
|
/// switches to ocean floor pattern if ocean is reached. Always adds bedrock at the very bottom.
|
||||||
|
void FillColumnPattern(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const sBlockInfo * a_Pattern);
|
||||||
|
|
||||||
|
/// Fills the specified column with mesa pattern, based on the column height
|
||||||
|
void FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ);
|
||||||
|
|
||||||
|
/// Returns the pattern to use for an ocean floor in the specified column
|
||||||
|
const sBlockInfo * ChooseOceanFloorPattern(int a_RelX, int a_RelZ);
|
||||||
|
|
||||||
|
|
||||||
// cTerrainHeightGen overrides:
|
// cTerrainHeightGen overrides:
|
||||||
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
|
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
|
||||||
|
Loading…
Reference in New Issue
Block a user