diff options
Diffstat (limited to 'src/Generating')
-rw-r--r-- | src/Generating/BioGen.cpp | 262 | ||||
-rw-r--r-- | src/Generating/BioGen.h | 38 | ||||
-rw-r--r-- | src/Generating/CompoGen.cpp | 90 | ||||
-rw-r--r-- | src/Generating/CompoGen.h | 2 | ||||
-rw-r--r-- | src/Generating/ComposableGenerator.cpp | 49 | ||||
-rw-r--r-- | src/Generating/ComposableGenerator.h | 7 | ||||
-rw-r--r-- | src/Generating/DistortedHeightmap.cpp | 686 | ||||
-rw-r--r-- | src/Generating/DistortedHeightmap.h | 30 | ||||
-rw-r--r-- | src/Generating/HeiGen.cpp | 126 | ||||
-rw-r--r-- | src/Generating/HeiGen.h | 2 | ||||
-rw-r--r-- | src/Generating/StructGen.cpp | 65 | ||||
-rw-r--r-- | src/Generating/Trees.cpp | 50 |
12 files changed, 1196 insertions, 211 deletions
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 8b2b227a8..a0407a145 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -13,6 +13,72 @@ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cBiomeGen: + +cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault) +{ + AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", ""); + if (BiomeGenName.empty()) + { + LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\"."); + BiomeGenName = "MultiStepMap"; + } + + cBiomeGen * res = NULL; + a_CacheOffByDefault = false; + if (NoCaseCompare(BiomeGenName, "constant") == 0) + { + res = new cBioGenConstant; + a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :) + } + else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0) + { + res = new cBioGenCheckerboard; + a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data + } + else if (NoCaseCompare(BiomeGenName, "voronoi") == 0) + { + res = new cBioGenVoronoi(a_Seed); + } + else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0) + { + res = new cBioGenDistortedVoronoi(a_Seed); + } + else if (NoCaseCompare(BiomeGenName, "twolevel") == 0) + { + res = new cBioGenTwoLevel(a_Seed); + } + else + { + if (NoCaseCompare(BiomeGenName, "multistepmap") != 0) + { + LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str()); + } + res = new cBioGenMultiStepMap(a_Seed); + + /* + // Performance-testing: + LOGINFO("Measuring performance of cBioGenMultiStepMap..."); + clock_t BeginTick = clock(); + for (int x = 0; x < 5000; x++) + { + cChunkDef::BiomeMap Biomes; + res->GenBiomes(x * 5, x * 5, Biomes); + } + clock_t Duration = clock() - BeginTick; + LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); + //*/ + } + res->InitializeBiomeGen(a_IniFile); + + return res; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cBioGenConstant: void cBioGenConstant::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) @@ -229,11 +295,12 @@ void cBioGenCheckerboard::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::Biome { for (int z = 0; z < cChunkDef::Width; z++) { - int Base = cChunkDef::Width * a_ChunkZ + z; + int Base = (cChunkDef::Width * a_ChunkZ + z) / m_BiomeSize; for (int x = 0; x < cChunkDef::Width; x++) { int Add = cChunkDef::Width * a_ChunkX + x; - a_BiomeMap[x + cChunkDef::Width * z] = m_Biomes[(Base / m_BiomeSize + Add / m_BiomeSize) % m_BiomesCount]; + int BiomeIdx = (((Base + Add / m_BiomeSize) % m_BiomesCount) + m_BiomesCount) % m_BiomesCount; // Need to add and modulo twice because of negative numbers + a_BiomeMap[x + cChunkDef::Width * z] = m_Biomes[BiomeIdx]; } } } @@ -669,3 +736,194 @@ void cBioGenMultiStepMap::FreezeWaterBiomes(cChunkDef::BiomeMap & a_BiomeMap, co + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cBioGenTwoLevel: + +cBioGenTwoLevel::cBioGenTwoLevel(int a_Seed) : + m_VoronoiLarge(a_Seed + 1000), + m_VoronoiSmall(a_Seed + 2000), + m_DistortX(a_Seed + 3000), + m_DistortZ(a_Seed + 4000), + m_Noise(a_Seed + 5000) +{ +} + + + + + +void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_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]; + for (int x = 0; x <= 4; x++) for (int z = 0; z <= 4; z++) + { + int BlockX = BaseX + x * 4; + int BlockZ = BaseZ + z * 4; + float BlockXF = (float)(16 * BlockX) / 128; + float BlockZF = (float)(16 * BlockZ) / 128; + double NoiseX = m_Noise.CubicNoise3D(BlockXF / 16, BlockZF / 16, 1000); + NoiseX += 0.5 * m_Noise.CubicNoise3D(BlockXF / 8, BlockZF / 8, 2000); + NoiseX += 0.08 * m_Noise.CubicNoise3D(BlockXF, BlockZF, 3000); + double NoiseZ = m_Noise.CubicNoise3D(BlockXF / 16, BlockZF / 16, 4000); + NoiseZ += 0.5 * m_Noise.CubicNoise3D(BlockXF / 8, BlockZF / 8, 5000); + NoiseZ += 0.08 * m_Noise.CubicNoise3D(BlockXF, BlockZF, 6000); + + DistortX[4 * x][4 * z] = BlockX + (int)(64 * NoiseX); + DistortZ[4 * x][4 * z] = BlockZ + (int)(64 * NoiseZ); + } + + LinearUpscale2DArrayInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); + LinearUpscale2DArrayInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4); + + // 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++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z]) / 7; + int MinDist1, MinDist2; + int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 11; + cChunkDef::SetBiome(a_BiomeMap, x, z, SelectBiome(BiomeGroup, BiomeIdx, (MinDist1 < MinDist2 / 4) ? 0 : 1)); + } + } +} + + + + + +EMCSBiome cBioGenTwoLevel::SelectBiome(int a_BiomeGroup, int a_BiomeIdx, int a_DistLevel) +{ + // TODO: Move this into settings + struct BiomeLevels + { + EMCSBiome InnerBiome; + EMCSBiome OuterBiome; + } ; + + static BiomeLevels bgOcean[] = + { + { biOcean, biOcean, }, + { biOcean, biOcean, }, + { biOcean, biOcean, }, + { biOcean, biOcean, }, + { biOcean, biDeepOcean, }, + { biOcean, biDeepOcean, }, + { biDeepOcean, biDeepOcean, }, + { biDeepOcean, biDeepOcean, }, + { biDeepOcean, biDeepOcean, }, + { biDeepOcean, biDeepOcean, }, + { biMushroomIsland, biMushroomShore, } + } ; + static BiomeLevels bgFrozen[] = + { + { biIcePlains, biIcePlains, }, + { biIceMountains, biIceMountains, }, + { biFrozenOcean, biFrozenRiver, }, + { biColdTaiga, biColdTaiga, }, + { biColdTaigaHills, biColdTaigaHills, }, + { biColdTaigaM, biColdTaigaM, }, + { biIcePlainsSpikes, biIcePlainsSpikes, }, + { biExtremeHills, biExtremeHillsEdge, }, + { biExtremeHillsPlus, biExtremeHillsEdge, }, + { biExtremeHillsPlusM, biExtremeHillsPlusM, }, + } ; + static BiomeLevels bgTemperate[] = + { + { biBirchForestHills, biBirchForest, }, + { biBirchForest, biBirchForest, }, + { biBirchForestHillsM, biBirchForestM, }, + { biBirchForestM, biBirchForestM, }, + { biForest, biForestHills, }, + { biFlowerForest, biFlowerForest, }, + { biRoofedForest, biForest, }, + { biRoofedForest, biRoofedForest, }, + { biRoofedForestM, biForest, }, + { biPlains, biPlains, }, + { biSunflowerPlains, biSunflowerPlains, }, + { biSwampland, biSwampland, }, + { biSwamplandM, biSwamplandM, }, + } ; + static BiomeLevels bgWarm[] = + { + { biDesertHills, biDesert, }, + { biDesert, biDesert, }, + { biDesertM, biDesertM, }, + { biSavannaPlateau, biSavanna, }, + { biSavanna, biSavanna, }, + { biSavannaM, biSavannaM, }, + } ; + static BiomeLevels bgMesa[] = + { + { biMesaPlateau, biMesa, }, + { biMesaPlateauF, biMesa, }, + { biMesaPlateauFM, biMesa, }, + { biMesaPlateauM, biMesa, }, + { biMesaBryce, biMesaBryce, }, + { biSavanna, biSavanna, }, + { biSavannaPlateau, biSavanna, }, + } ; + static BiomeLevels bgConifers[] = + { + { biTaiga, biTaiga, }, + { biTaigaM, biTaigaM, }, + { biMegaTaiga, biMegaTaiga, }, + { biMegaSpruceTaiga, biMegaSpruceTaiga, }, + { biMegaSpruceTaigaHills, biMegaSpruceTaiga, } + } ; + static BiomeLevels bgDenseTrees[] = + { + { biJungleHills, biJungle, }, + { biJungle, biJungleEdge, }, + { biJungleM, biJungleEdgeM, }, + } ; + static struct + { + BiomeLevels * Biomes; + size_t Count; + } BiomeGroups[] = + { + { bgOcean, ARRAYCOUNT(bgOcean), }, + { bgOcean, ARRAYCOUNT(bgOcean), }, + { bgFrozen, ARRAYCOUNT(bgFrozen), }, + { bgFrozen, ARRAYCOUNT(bgFrozen), }, + { bgTemperate, ARRAYCOUNT(bgTemperate), }, + { bgTemperate, ARRAYCOUNT(bgTemperate), }, + { bgConifers, ARRAYCOUNT(bgConifers), }, + { bgConifers, ARRAYCOUNT(bgConifers), }, + { bgWarm, ARRAYCOUNT(bgWarm), }, + { bgWarm, ARRAYCOUNT(bgWarm), }, + { bgMesa, ARRAYCOUNT(bgMesa), }, + { bgDenseTrees, ARRAYCOUNT(bgDenseTrees), }, + } ; + size_t Group = a_BiomeGroup % ARRAYCOUNT(BiomeGroups); + size_t Index = a_BiomeIdx % BiomeGroups[Group].Count; + return (a_DistLevel > 0) ? BiomeGroups[Group].Biomes[Index].InnerBiome : BiomeGroups[Group].Biomes[Index].OuterBiome; +} + + + + + +void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile) +{ + // TODO: Read these from a file + m_VoronoiLarge.SetCellSize(1024); + m_VoronoiSmall.SetCellSize(128); + m_DistortX.AddOctave(0.01f, 16); + m_DistortX.AddOctave(0.005f, 8); + m_DistortX.AddOctave(0.0025f, 4); + m_DistortZ.AddOctave(0.01f, 16); + m_DistortZ.AddOctave(0.005f, 8); + m_DistortZ.AddOctave(0.0025f, 4); +} + + + + diff --git a/src/Generating/BioGen.h b/src/Generating/BioGen.h index 892168bb6..8bd460d8f 100644 --- a/src/Generating/BioGen.h +++ b/src/Generating/BioGen.h @@ -239,3 +239,41 @@ protected: + +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 noise used to distort the input X coord + cPerlinNoise m_DistortX; + + /// The noise used to distort the inupt Z coord + cPerlinNoise m_DistortZ; + + cNoise m_Noise; + + + // cBiomeGen overrides: + virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override; + virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; + + /// Selects biome from the specified biome group, based on the specified index. + /// Note that both params may overflow + /// a_DistLevel is either 0 or 1; zero when it is at the edge of the small Voronoi cell, 1 near the center + EMCSBiome SelectBiome(int a_BiomeGroup, int a_BiomeIdx, int a_DistLevel); +} ; + + + + diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 03a65a457..f929ddc2f 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -250,12 +250,61 @@ void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc) 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: { FillColumnGrass(x, z, Height, a_ChunkDesc.GetBlockTypes()); break; } + + case biMesa: + case biMesaPlateauF: + case biMesaPlateau: + case biMesaBryce: + case biMesaPlateauFM: + case biMesaPlateauM: + { + FillColumnClay(x, z, Height, a_ChunkDesc.GetBlockTypes()); + break; + } + + case biMegaTaiga: + case biMegaTaigaHills: + case biMegaSpruceTaiga: + case biMegaSpruceTaigaHills: + { + FillColumnDirt(x, z, Height, a_ChunkDesc.GetBlockTypes()); + break; + } + case biDesertHills: case biDesert: + case biDesertM: case biBeach: { FillColumnSand(x, z, Height, a_ChunkDesc.GetBlockTypes()); @@ -341,6 +390,47 @@ void cCompoGenBiomal::FillColumnGrass(int a_RelX, int a_RelZ, int a_Height, cChu +void cCompoGenBiomal::FillColumnClay(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) +{ + BLOCKTYPE Pattern[] = + { + E_BLOCK_HARDENED_CLAY, + E_BLOCK_HARDENED_CLAY, + E_BLOCK_HARDENED_CLAY, + E_BLOCK_HARDENED_CLAY, + } ; + FillColumnPattern(a_RelX, a_RelZ, a_Height, a_BlockTypes, Pattern, ARRAYCOUNT(Pattern)); + + for (int y = a_Height - ARRAYCOUNT(Pattern); y > 0; y--) + { + cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, E_BLOCK_STONE); + } +} + + + + + +void cCompoGenBiomal::FillColumnDirt(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) +{ + for (int y = 0; y < 4; y++) + { + if (a_Height - y < 0) + { + return; + } + cChunkDef::SetBlock(a_BlockTypes, a_RelX, a_Height - y, a_RelZ, E_BLOCK_DIRT); + } + for (int y = a_Height - 4; y > 0; y--) + { + cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, E_BLOCK_STONE); + } +} + + + + + void cCompoGenBiomal::FillColumnSand(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) { BLOCKTYPE Pattern[] = diff --git a/src/Generating/CompoGen.h b/src/Generating/CompoGen.h index 2ee286b06..096b0fb5a 100644 --- a/src/Generating/CompoGen.h +++ b/src/Generating/CompoGen.h @@ -109,6 +109,8 @@ protected: virtual void InitializeCompoGen(cIniFile & a_IniFile) override; void FillColumnGrass (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); + void FillColumnClay (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); + void FillColumnDirt (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); void FillColumnSand (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); void FillColumnMycelium (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); void FillColumnWaterSand(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 01070963c..c86568c95 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -147,54 +147,8 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile) { - AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", ""); - if (BiomeGenName.empty()) - { - LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\"."); - BiomeGenName = "MultiStepMap"; - } - - int Seed = m_ChunkGenerator.GetSeed(); bool CacheOffByDefault = false; - if (NoCaseCompare(BiomeGenName, "constant") == 0) - { - m_BiomeGen = new cBioGenConstant; - CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :) - } - else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0) - { - m_BiomeGen = new cBioGenCheckerboard; - CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data - } - else if (NoCaseCompare(BiomeGenName, "voronoi") == 0) - { - m_BiomeGen = new cBioGenVoronoi(Seed); - } - else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0) - { - m_BiomeGen = new cBioGenDistortedVoronoi(Seed); - } - else - { - if (NoCaseCompare(BiomeGenName, "multistepmap") != 0) - { - LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str()); - } - m_BiomeGen = new cBioGenMultiStepMap(Seed); - - /* - // Performance-testing: - LOGINFO("Measuring performance of cBioGenMultiStepMap..."); - clock_t BeginTick = clock(); - for (int x = 0; x < 5000; x++) - { - cChunkDef::BiomeMap Biomes; - m_BiomeGen->GenBiomes(x * 5, x * 5, Biomes); - } - clock_t Duration = clock() - BeginTick; - LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); - //*/ - } + m_BiomeGen = cBiomeGen::CreateBiomeGen(a_IniFile, m_ChunkGenerator.GetSeed(), CacheOffByDefault); // Add a cache, if requested: int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 64); @@ -211,7 +165,6 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile) m_UnderlyingBiomeGen = m_BiomeGen; m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize); } - m_BiomeGen->InitializeBiomeGen(a_IniFile); } diff --git a/src/Generating/ComposableGenerator.h b/src/Generating/ComposableGenerator.h index d5e33a439..732f64303 100644 --- a/src/Generating/ComposableGenerator.h +++ b/src/Generating/ComposableGenerator.h @@ -48,6 +48,13 @@ public: /// Reads parameters from the ini file, prepares generator for use. virtual void InitializeBiomeGen(cIniFile & a_IniFile) {} + + /// Creates the correct BiomeGen descendant based on the ini file settings and the seed provided. + /// a_CacheOffByDefault gets set to whether the cache should be enabled by default + /// Used in BiomeVisualiser, too. + /// Implemented in BioGen.cpp! + static cBiomeGen * CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault); + } ; diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index 95ea812fa..a61d79bec 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -14,6 +14,150 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// 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}, +} ; + +static cDistortedHeightmap::sBlockInfo tbOFRedSand[] = +{ + { E_BLOCK_SAND, E_META_SAND_RED}, + { E_BLOCK_SAND, E_META_SAND_RED}, + { E_BLOCK_SAND, E_META_SAND_RED}, + { E_BLOCK_SANDSTONE, 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)); +static cPattern patOFRedSand(tbOFRedSand, ARRAYCOUNT(tbOFRedSand)); + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cDistortedHeightmap: + /** 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; this means that you can have different-sized overhangs in each direction. @@ -21,7 +165,7 @@ Usually you'd want to keep both numbers the same. The numbers are "relative", not absolute maximum; overhangs of a slightly larger size are possible due to the way that noise is calculated. */ -const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[biNumBiomes] = +const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = { /* Biome | AmpX | AmpZ */ /* biOcean */ { 1.5f, 1.5f}, @@ -46,8 +190,70 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[biNumBiomes /* biForestHills */ { 6.0f, 6.0f}, /* biTaigaHills */ { 8.0f, 8.0f}, /* biExtremeHillsEdge */ { 7.0f, 7.0f}, - /* biJungle */ { 0.0f, 0.0f}, + /* biJungle */ { 4.0f, 4.0f}, /* biJungleHills */ { 8.0f, 8.0f}, + /* biJungleEdge */ { 3.0f, 3.0f}, // 23 + /* biDeepOcean */ { 1.0f, 1.0f}, // 24 + /* biStoneBeach */ { 1.0f, 1.0f}, // 25 + /* biColdBeach */ { 1.0f, 1.0f}, // 26 + /* biBirchForest */ { 3.0f, 3.0f}, // 27 + /* biBirchForestHills */ { 6.0f, 6.0f}, // 28 + /* biRoofedForest */ { 3.0f, 3.0f}, // 29 + /* biColdTaiga */ { 0.5f, 0.5f}, // 30 + /* biColdTaigaHills */ { 4.0f, 4.0f}, // 31 + /* biMegaTaiga */ { 1.0f, 1.0f}, // 32 + /* biMegaTaigaHills */ { 4.0f, 4.0f}, // 33 + /* biExtremeHillsPlus */ {32.0f, 32.0f}, // 34 - anyone say extreme plus? Make it extreme plus, then :) + /* biSavanna */ { 2.0f, 2.0f}, // 35 + /* biSavannaPlateau */ { 3.0f, 3.0f}, // 36 + /* 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: + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 40 .. 49 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 50 .. 59 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 60 .. 69 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 70 .. 79 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 80 .. 89 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 90 .. 99 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 100 .. 109 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 110 .. 119 + {}, {}, {}, {}, {}, {}, {}, {}, {}, // 120 .. 128 + + // Release 1.7 /* biome variants: + /* biSunflowerPlains */ { 1.0f, 1.0f}, // 129 + /* biDesertM */ { 1.0f, 1.0f}, // 130 + /* biExtremeHillsM */ {16.0f, 16.0f}, // 131 + /* 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: + {}, {}, {}, {}, {}, // 135 .. 139 + + /* biIcePlainsSpikes */ { 1.0f, 1.0f}, // 140 + + // Biomes 141 .. 148 unused, 8 empty placeholders here: + {}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148 + + /* biJungleM */ { 4.0f, 4.0f}, // 149 + {}, // 150 + /* biJungleEdgeM */ { 3.0f, 3.0f}, // 151 + {}, {}, {}, // 152 .. 154 + /* biBirchForestM */ { 3.0f, 3.0f}, // 155 + /* biBirchForestHillsM */ { 5.0f, 5.0f}, // 156 + /* biRoofedForestM */ { 2.0f, 2.0f}, // 157 + /* biColdTaigaM */ { 1.0f, 1.0f}, // 158 + {}, // 159 + /* biMegaSpruceTaiga */ { 3.0f, 3.0f}, // 160 + /* biMegaSpruceTaigaHills */ { 3.0f, 3.0f}, // 161 + /* biExtremeHillsPlusM */ {32.0f, 32.0f}, // 162 + /* biSavannaM */ { 2.0f, 2.0f}, // 163 + /* biSavannaPlateauM */ { 3.0f, 3.0f}, // 164 + /* biMesaBryce */ { 0.5f, 0.5f}, // 165 + /* biMesaPlateauFM */ { 2.0f, 2.0f}, // 166 + /* biMesaPlateauM */ { 2.0f, 2.0f}, // 167 } ; @@ -58,9 +264,11 @@ cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen) : m_NoiseDistortX(a_Seed + 1000), m_NoiseDistortZ(a_Seed + 2000), m_OceanFloorSelect(a_Seed + 3000), + m_MesaFloor(a_Seed + 4000), m_BiomeGen(a_BiomeGen), m_UnderlyingHeiGen(a_Seed, a_BiomeGen), - m_HeightGen(m_UnderlyingHeiGen, 64) + m_HeightGen(m_UnderlyingHeiGen, 64), + m_IsInitialized(false) { m_NoiseDistortX.AddOctave((NOISE_DATATYPE)1, (NOISE_DATATYPE)0.5); m_NoiseDistortX.AddOctave((NOISE_DATATYPE)0.5, (NOISE_DATATYPE)1); @@ -69,6 +277,8 @@ cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen) : 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.25, (NOISE_DATATYPE)2); + + InitMesaPattern(a_Seed); } @@ -95,6 +305,89 @@ void cDistortedHeightmap::Initialize(cIniFile & a_IniFile) +void cDistortedHeightmap::InitMesaPattern(int a_Seed) +{ + // Stone in the bottom half of the pattern: + for (int i = cChunkDef::Height; i < 2 * cChunkDef::Height; i++) + { + m_MesaPattern[i].BlockMeta = 0; + m_MesaPattern[i].BlockType = E_BLOCK_STONE; + } + + // Stained and hardened clay in the top half of the pattern + // In a loop, choose whether to use one or two layers of stained clay, then choose a color and width for each layer + // Separate each group with another layer of hardened clay + cNoise PatternNoise((unsigned)a_Seed); + static NIBBLETYPE AllowedColors[] = + { + E_META_STAINED_CLAY_YELLOW, + E_META_STAINED_CLAY_YELLOW, + E_META_STAINED_CLAY_RED, + E_META_STAINED_CLAY_RED, + E_META_STAINED_CLAY_WHITE, + E_META_STAINED_CLAY_BROWN, + E_META_STAINED_CLAY_BROWN, + E_META_STAINED_CLAY_BROWN, + E_META_STAINED_CLAY_ORANGE, + E_META_STAINED_CLAY_ORANGE, + E_META_STAINED_CLAY_ORANGE, + E_META_STAINED_CLAY_ORANGE, + E_META_STAINED_CLAY_ORANGE, + E_META_STAINED_CLAY_ORANGE, + E_META_STAINED_CLAY_LIGHTGRAY, + } ; + static int LayerSizes[] = // Adjust the chance so that thinner layers occur more commonly + { + 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, + 3, 3, + } ; + int Idx = cChunkDef::Height - 1; + while (Idx >= 0) + { + // A layer group of 1 - 2 color stained clay: + int Random = PatternNoise.IntNoise1DInt(Idx) / 7; + int NumLayers = (Random % 2) + 1; + Random /= 2; + for (int Lay = 0; Lay < NumLayers; Lay++) + { + int NumBlocks = LayerSizes[(Random % ARRAYCOUNT(LayerSizes))]; + NIBBLETYPE Color = AllowedColors[(Random / 4) % ARRAYCOUNT(AllowedColors)]; + if ( + ((NumBlocks == 3) && (NumLayers == 2)) || // In two-layer mode disallow the 3-high layers: + (Color == E_META_STAINED_CLAY_WHITE)) // White stained clay can ever be only 1 block high + { + NumBlocks = 1; + } + NumBlocks = std::min(Idx + 1, NumBlocks); // Limit by Idx so that we don't have to check inside the loop + Random /= 32; + for (int Block = 0; Block < NumBlocks; Block++, Idx--) + { + m_MesaPattern[Idx].BlockMeta = Color; + m_MesaPattern[Idx].BlockType = E_BLOCK_STAINED_CLAY; + } // for Block + } // for Lay + + // A layer of hardened clay in between the layer group: + int NumBlocks = (Random % 4) + 1; // All heights the same probability + if ((NumLayers == 2) && (NumBlocks < 4)) + { + // For two layers of stained clay, add an extra block of hardened clay: + NumBlocks++; + } + NumBlocks = std::min(Idx + 1, NumBlocks); // Limit by Idx so that we don't have to check inside the loop + for (int Block = 0; Block < NumBlocks; Block++, Idx--) + { + m_MesaPattern[Idx].BlockMeta = 0; + m_MesaPattern[Idx].BlockType = E_BLOCK_HARDENED_CLAY; + } // for Block + } // while (Idx >= 0) +} + + + + + void cDistortedHeightmap::PrepareState(int a_ChunkX, int a_ChunkZ) { if ((m_CurChunkX == a_ChunkX) && (m_CurChunkZ == a_ChunkZ)) @@ -202,10 +495,6 @@ void cDistortedHeightmap::InitializeHeightGen(cIniFile & a_IniFile) 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: PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); @@ -215,110 +504,7 @@ void cDistortedHeightmap::ComposeTerrain(cChunkDesc & a_ChunkDesc) { for (int x = 0; x < cChunkDef::Width; x++) { - int NoiseArrayIdx = x + 17 * 257 * 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: - { - a_ChunkDesc.SetBlockType(x, y, z, (y == LastAir - 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); - break; - } - case biDesertHills: - case biDesert: - 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); + ComposeColumn(a_ChunkDesc, x, z); } // for x } // for z } @@ -394,7 +580,7 @@ void cDistortedHeightmap::UpdateDistortAmps(void) void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_RelX, int a_RelZ, NOISE_DATATYPE & a_DistortAmpX, NOISE_DATATYPE & a_DistortAmpZ) { // Sum up how many biomes of each type there are in the neighborhood: - int BiomeCounts[biNumBiomes]; + int BiomeCounts[256]; memset(BiomeCounts, 0, sizeof(BiomeCounts)); int Sum = 0; for (int z = -8; z <= 8; z++) @@ -409,10 +595,6 @@ void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_R int IdxX = FinalX / cChunkDef::Width; int ModX = FinalX % cChunkDef::Width; EMCSBiome Biome = cChunkDef::GetBiome(a_Neighbors[IdxX][IdxZ], ModX, ModZ); - if ((Biome < 0) || (Biome >= ARRAYCOUNT(BiomeCounts))) - { - continue; - } int WeightX = 9 - abs(x); BiomeCounts[Biome] += WeightX + WeightZ; Sum += WeightX + WeightZ; @@ -432,6 +614,19 @@ void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_R NOISE_DATATYPE AmpZ = 0; for (unsigned int i = 0; i < ARRAYCOUNT(BiomeCounts); i++) { + if (BiomeCounts[i] <= 0) + { + continue; + } + + /* + // Sanity checks for biome parameters, enable them to check the biome param table in runtime (slow): + ASSERT(m_GenParam[i].m_DistortAmpX >= 0); + ASSERT(m_GenParam[i].m_DistortAmpX < 100); + ASSERT(m_GenParam[i].m_DistortAmpX >= 0); + ASSERT(m_GenParam[i].m_DistortAmpX < 100); + */ + AmpX += BiomeCounts[i] * m_GenParam[i].m_DistortAmpX; AmpZ += BiomeCounts[i] * m_GenParam[i].m_DistortAmpZ; } @@ -442,3 +637,262 @@ void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_R +void cDistortedHeightmap::ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ) +{ + // 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) + { + 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: + { + // Select the pattern to use - podzol, grass or grassless dirt: + 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); + const sBlockInfo * Pattern = (Val < -0.9) ? patGrassLess.Get() : ((Val > 0) ? patPodzol.Get() : patGrass.Get()); + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern); + 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 ocean: + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patOFRedSand.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 - m_SeaLevel < 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(); + } +} + + + + diff --git a/src/Generating/DistortedHeightmap.h b/src/Generating/DistortedHeightmap.h index 6d7007375..e6b3c9d3f 100644 --- a/src/Generating/DistortedHeightmap.h +++ b/src/Generating/DistortedHeightmap.h @@ -28,6 +28,13 @@ class cDistortedHeightmap : public cTerrainCompositionGen { public: + /// Structure used for storing block patterns for columns + struct sBlockInfo + { + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + } ; + cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen); protected: @@ -46,6 +53,7 @@ protected: cPerlinNoise m_NoiseDistortX; cPerlinNoise m_NoiseDistortZ; 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; NOISE_DATATYPE m_FrequencyX; @@ -69,7 +77,7 @@ protected: NOISE_DATATYPE m_DistortAmpX; NOISE_DATATYPE m_DistortAmpZ; } ; - static const sGenParam m_GenParam[biNumBiomes]; + static const sGenParam m_GenParam[256]; // Distortion amplitudes for each direction, before linear upscaling NOISE_DATATYPE m_DistortAmpX[DIM_X * DIM_Z]; @@ -78,7 +86,14 @@ protected: /// True if Initialize() has been called. Used to initialize-once even with multiple init entrypoints (HeiGen / CompoGen) 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]; + + /// Initializes m_MesaPattern with a reasonable pattern of stained clay / hardened clay, based on the seed + void InitMesaPattern(int a_Seed); + /// Unless the LastChunk coords are equal to coords given, prepares the internal state (noise arrays, heightmap) void PrepareState(int a_ChunkX, int a_ChunkZ); @@ -97,6 +112,19 @@ protected: /// Reads the settings from the ini file. Skips reading if already initialized 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: virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 8aab3fe15..ea6051371 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -229,33 +229,94 @@ void cHeiGenClassic::InitializeHeightGen(cIniFile & a_IniFile) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cHeiGenBiomal: -const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[biNumBiomes] = +const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] = { /* Fast-changing | Middle-changing | Slow-changing |*/ /* Biome | Freq1 | Amp1 | Freq2 | Amp2 | Freq3 | Amp3 | BaseHeight */ - /* biOcean */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, - /* biPlains */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, - /* biDesert */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, - /* biExtremeHills */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 100}, - /* biForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, - /* biTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, - /* biSwampland */ { 0.1f, 1.1f, 0.05f, 1.5f, 0.02f, 2.5f, 61.5}, - /* biRiver */ { 0.2f, 0.1f, 0.05f, 0.1f, 0.01f, 0.1f, 56}, - /* biNether */ { 0.1f, 0.0f, 0.01f, 0.0f, 0.01f, 0.0f, 0}, // Unused, but must be here due to indexing - /* biSky */ { 0.1f, 0.0f, 0.01f, 0.0f, 0.01f, 0.0f, 0}, // Unused, but must be here due to indexing - /* biFrozenOcean */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, - /* biFrozenRiver */ { 0.2f, 0.1f, 0.05f, 0.1f, 0.01f, 0.1f, 56}, - /* biIcePlains */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, - /* biIceMountains */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, - /* biMushroomIsland */ { 0.1f, 2.0f, 0.05f, 8.0f, 0.01f, 6.0f, 80}, - /* biMushroomShore */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 64}, - /* biBeach */ { 0.1f, 0.5f, 0.05f, 1.0f, 0.01f, 1.0f, 64}, - /* biDesertHills */ { 0.2f, 2.0f, 0.05f, 5.0f, 0.01f, 4.0f, 75}, - /* biForestHills */ { 0.2f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, - /* biTaigaHills */ { 0.2f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, - /* biExtremeHillsEdge */ { 0.2f, 3.0f, 0.05f, 16.0f, 0.01f, 12.0f, 80}, - /* biJungle */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, - /* biJungleHills */ { 0.2f, 3.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, + /* biOcean */ { 0.1f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 50}, + /* biPlains */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, + /* biDesert */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, + /* biExtremeHills */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 100}, + /* biForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, + /* biTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, + /* biSwampland */ { 0.1f, 1.1f, 0.05f, 1.5f, 0.02f, 2.5f, 61.5}, + /* biRiver */ { 0.2f, 0.1f, 0.05f, 0.1f, 0.01f, 0.1f, 56}, + /* biNether */ { 0.1f, 0.0f, 0.01f, 0.0f, 0.01f, 0.0f, 0}, // Unused, but must be here due to indexing + /* biSky */ { 0.1f, 0.0f, 0.01f, 0.0f, 0.01f, 0.0f, 0}, // Unused, but must be here due to indexing + /* biFrozenOcean */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, + /* biFrozenRiver */ { 0.2f, 0.1f, 0.05f, 0.1f, 0.01f, 0.1f, 56}, + /* biIcePlains */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, + /* biIceMountains */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, + /* biMushroomIsland */ { 0.1f, 2.0f, 0.05f, 8.0f, 0.01f, 6.0f, 80}, + /* biMushroomShore */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 64}, + /* biBeach */ { 0.1f, 0.5f, 0.05f, 1.0f, 0.01f, 1.0f, 64}, + /* biDesertHills */ { 0.2f, 2.0f, 0.05f, 5.0f, 0.01f, 4.0f, 75}, + /* biForestHills */ { 0.2f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, + /* biTaigaHills */ { 0.2f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, + /* biExtremeHillsEdge */ { 0.2f, 3.0f, 0.05f, 16.0f, 0.01f, 12.0f, 80}, + /* biJungle */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, + /* biJungleHills */ { 0.2f, 3.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, + /* biJungleEdge */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, + /* biDeepOcean */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, + /* biStoneBeach */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, + /* biColdBeach */ { 0.1f, 0.5f, 0.05f, 1.0f, 0.01f, 1.0f, 64}, + /* biBirchForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, + /* biBirchForestHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, + /* biRoofedForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, + /* biColdTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, + /* biColdTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, + /* biMegaTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, + /* biMegaTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, + /* biExtremeHillsPlus */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 120}, + /* biSavanna */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, + /* biSavannaPlateau */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, + /* 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: + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 40 .. 49 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 50 .. 59 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 60 .. 69 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 70 .. 79 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 80 .. 89 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 90 .. 99 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 100 .. 109 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 110 .. 119 + {}, {}, {}, {}, {}, {}, {}, {}, {}, // 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 */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 134 + + // Biomes 135 .. 139 unused, 5 empty placeholders here: + {}, {}, {}, {}, {}, // 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: + {}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148 + + /* biJungleM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 149 + {}, // 150 + /* biJungleEdgeM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 151 + {}, {}, {}, // 152 .. 154 + /* biBirchForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 155 + /* biBirchForestHillsM */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 156 + /* biRoofedForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 157 + /* biColdTaigaM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 158 + {}, // 159 + /* biMegaSpruceTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 160 + /* biMegaSpruceTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 161 + /* biExtremeHillsPlusM */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 120}, // 162 + /* biSavannaM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, // 163 + /* biSavannaPlateauM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // 164 + /* biMesaBryce */ { 0.2f, 2.0f, 0.1f, 30.0f, 0.01f, 8.0f, 80}, + /* biMesaPlateauFM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // 166 + /* biMesaPlateauM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // 167 } ; @@ -333,7 +394,7 @@ void cHeiGenBiomal::InitializeHeightGen(cIniFile & a_IniFile) NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, int a_ChunkZ, const cHeiGenBiomal::BiomeNeighbors & a_BiomeNeighbors) { // Sum up how many biomes of each type there are in the neighborhood: - int BiomeCounts[biNumBiomes]; + int BiomeCounts[256]; memset(BiomeCounts, 0, sizeof(BiomeCounts)); int Sum = 0; for (int z = -8; z <= 8; z++) @@ -348,10 +409,6 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, int IdxX = FinalX / cChunkDef::Width; int ModX = FinalX % cChunkDef::Width; EMCSBiome Biome = cChunkDef::GetBiome(a_BiomeNeighbors[IdxX][IdxZ], ModX, ModZ); - if ((Biome < 0) || (Biome >= ARRAYCOUNT(BiomeCounts))) - { - continue; - } int WeightX = 9 - abs(x); BiomeCounts[Biome] += WeightX + WeightZ; Sum += WeightX + WeightZ; @@ -370,6 +427,17 @@ 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); + ASSERT(m_GenParam[i].m_HeightFreq1 < 1000); + ASSERT(m_GenParam[i].m_HeightFreq2 >= 0); + ASSERT(m_GenParam[i].m_HeightFreq2 < 1000); + 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; diff --git a/src/Generating/HeiGen.h b/src/Generating/HeiGen.h index 1b246c70a..1376f2a25 100644 --- a/src/Generating/HeiGen.h +++ b/src/Generating/HeiGen.h @@ -131,7 +131,7 @@ protected: float m_HeightFreq3, m_HeightAmp3; float m_BaseHeight; } ; - static const sGenParam m_GenParam[biNumBiomes]; + static const sGenParam m_GenParam[256]; // cTerrainHeightGen overrides: virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp index 2180261aa..504c26238 100644 --- a/src/Generating/StructGen.cpp +++ b/src/Generating/StructGen.cpp @@ -260,20 +260,57 @@ int cStructGenTrees::GetNumTrees( int Add = 0; switch (cChunkDef::GetBiome(a_Biomes, x, z)) { - case biPlains: Add = 1; break; - case biExtremeHills: Add = 3; break; - case biForest: Add = 30; break; - case biTaiga: Add = 30; break; - case biSwampland: Add = 8; break; - case biIcePlains: Add = 1; break; - case biIceMountains: Add = 1; break; - case biMushroomIsland: Add = 3; break; - case biMushroomShore: Add = 3; break; - case biForestHills: Add = 20; break; - case biTaigaHills: Add = 20; break; - case biExtremeHillsEdge: Add = 5; break; - case biJungle: Add = 120; break; - case biJungleHills: Add = 90; break; + case biOcean: Add = 2; break; + case biDesert: Add = 0; break; + case biPlains: Add = 1; break; + case biExtremeHills: Add = 3; break; + case biForest: Add = 30; break; + case biTaiga: Add = 30; break; + case biSwampland: Add = 8; break; + case biIcePlains: Add = 1; break; + case biIceMountains: Add = 1; break; + case biMushroomIsland: Add = 3; break; + case biMushroomShore: Add = 3; break; + case biForestHills: Add = 20; break; + case biTaigaHills: Add = 20; break; + case biExtremeHillsEdge: Add = 5; break; + case biJungle: Add = 120; break; + case biJungleHills: Add = 90; break; + case biJungleEdge: Add = 90; break; + case biBirchForest: Add = 30; break; + case biBirchForestHills: Add = 20; break; + case biRoofedForest: Add = 50; break; + case biColdTaiga: Add = 20; break; + case biColdTaigaHills: Add = 15; break; + case biMegaTaiga: Add = 30; break; + case biMegaTaigaHills: Add = 25; break; + case biExtremeHillsPlus: Add = 3; break; + case biSavanna: Add = 8; break; + case biSavannaPlateau: Add = 12; break; + case biMesa: Add = 2; break; + case biMesaPlateauF: Add = 8; break; + case biMesaPlateau: Add = 8; break; + case biSunflowerPlains: Add = 1; break; + case biDesertM: Add = 0; break; + case biExtremeHillsM: Add = 4; break; + case biFlowerForest: Add = 30; break; + case biTaigaM: Add = 30; break; + case biSwamplandM: Add = 8; break; + case biIcePlainsSpikes: Add = 1; break; + case biJungleM: Add = 120; break; + case biJungleEdgeM: Add = 90; break; + case biBirchForestM: Add = 30; break; + case biBirchForestHillsM: Add = 20; break; + case biRoofedForestM: Add = 40; break; + case biColdTaigaM: Add = 30; break; + case biMegaSpruceTaiga: Add = 30; break; + case biMegaSpruceTaigaHills: Add = 30; break; + case biExtremeHillsPlusM: Add = 4; break; + case biSavannaM: Add = 8; break; + case biSavannaPlateauM: Add = 12; break; + case biMesaBryce: Add = 4; break; + case biMesaPlateauFM: Add = 12; break; + case biMesaPlateauM: Add = 12; break; } NumTrees += Add; } diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 7ca30c60f..fbed57cb6 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -161,6 +161,9 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No case biMushroomIsland: case biMushroomShore: case biForestHills: + case biDeepOcean: + case biStoneBeach: + case biColdBeach: { // Apple or birch trees: if (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + 16 * a_Seq, a_BlockZ + 16 * a_Seq) < 0x5fffffff) @@ -193,6 +196,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No case biJungle: case biJungleHills: + case biJungleEdge: { // Apple bushes, large jungle trees, small jungle trees if (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + 16 * a_Seq, a_BlockZ + 16 * a_Seq) < 0x6fffffff) @@ -203,6 +207,52 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No { GetJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } + break; + } + + case biBirchForest: + case biBirchForestHills: + { + GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); + break; + } + + case biRoofedForest: + case biColdTaiga: + case biColdTaigaHills: + case biMegaTaiga: + case biMegaTaigaHills: + case biExtremeHillsPlus: + case biSavanna: + case biSavannaPlateau: + case biMesa: + case biMesaPlateauF: + case biMesaPlateau: + case biSunflowerPlains: + case biDesertM: + case biExtremeHillsM: + case biFlowerForest: + case biTaigaM: + case biSwamplandM: + case biIcePlainsSpikes: + case biJungleM: + case biJungleEdgeM: + case biBirchForestM: + case biBirchForestHillsM: + case biRoofedForestM: + case biColdTaigaM: + case biMegaSpruceTaiga: + case biMegaSpruceTaigaHills: + case biExtremeHillsPlusM: + case biSavannaM: + case biSavannaPlateauM: + case biMesaBryce: + case biMesaPlateauFM: + case biMesaPlateauM: + { + // TODO: These need their special trees + GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); + break; } } } |