From aa19a3afb0b94e8b5fe055eeb38b1fb2ee1a67b0 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 19 Oct 2014 14:10:18 +0100 Subject: Migrated random generators to std::random --- src/Generating/ChunkGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index d615456c1..20b6b7066 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -6,7 +6,7 @@ #include "ChunkDesc.h" #include "ComposableGenerator.h" #include "Noise3DGenerator.h" -#include "../MersenneTwister.h" +#include "FastRandom.h" -- cgit v1.2.3 From 987f79afdd8945966d0dfa2d52539e005f771590 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 20 Oct 2014 21:55:07 +0100 Subject: En masse NULL -> nullptr replace --- src/Generating/BioGen.cpp | 6 +++--- src/Generating/ChunkDesc.cpp | 4 ++-- src/Generating/ChunkDesc.h | 2 +- src/Generating/ChunkGenerator.cpp | 18 +++++++++--------- src/Generating/CompoGen.cpp | 4 ++-- src/Generating/ComposableGenerator.cpp | 6 +++--- src/Generating/DungeonRoomsFinisher.cpp | 2 +- src/Generating/GridStructGen.cpp | 2 +- src/Generating/HeiGen.cpp | 6 +++--- src/Generating/MineShafts.cpp | 18 +++++++++--------- src/Generating/PieceGenerator.cpp | 4 ++-- src/Generating/Prefab.cpp | 6 +++--- src/Generating/PrefabPiecePool.cpp | 6 +++--- src/Generating/VillageGen.cpp | 4 ++-- 14 files changed, 44 insertions(+), 44 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index b9face1f8..d86d44bbc 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -69,9 +69,9 @@ cBioGenCache::cBioGenCache(cBiomeGenPtr a_BioGenToCache, int a_CacheSize) : cBioGenCache::~cBioGenCache() { delete[] m_CacheData; - m_CacheData = NULL; + m_CacheData = nullptr; delete[] m_CacheOrder; - m_CacheOrder = NULL; + m_CacheOrder = nullptr; } @@ -928,7 +928,7 @@ cBiomeGenPtr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & BiomeGenName = "MultiStepMap"; } - cBiomeGen * res = NULL; + cBiomeGen * res = nullptr; a_CacheOffByDefault = false; if (NoCaseCompare(BiomeGenName, "constant") == 0) { diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index 566332b1f..020d3bd0f 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -530,10 +530,10 @@ cBlockEntity * cChunkDesc::GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ) // 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 == NULL) + if (be == nullptr) { // No block entity for this block type - return NULL; + return nullptr; } m_BlockEntities.push_back(be); return be; diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index eeea0c957..570132790 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -172,7 +172,7 @@ public: /** 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 NULL. */ + 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. diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index 20b6b7066..b08b9411e 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -28,9 +28,9 @@ const unsigned int QUEUE_SKIP_LIMIT = 500; cChunkGenerator::cChunkGenerator(void) : super("cChunkGenerator"), m_Seed(0), // Will be overwritten by the actual generator - m_Generator(NULL), - m_PluginInterface(NULL), - m_ChunkSink(NULL) + m_Generator(nullptr), + m_PluginInterface(nullptr), + m_ChunkSink(nullptr) { } @@ -80,7 +80,7 @@ bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a m_Generator = new cComposableGenerator(*this); } - if (m_Generator == NULL) + if (m_Generator == nullptr) { LOGERROR("Generator could not start, aborting the server"); return false; @@ -103,7 +103,7 @@ void cChunkGenerator::Stop(void) Wait(); delete m_Generator; - m_Generator = NULL; + m_Generator = nullptr; } @@ -144,7 +144,7 @@ void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_Forc void cChunkGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) { - if (m_Generator != NULL) + if (m_Generator != nullptr) { m_Generator->GenerateBiomes(a_ChunkX, a_ChunkZ, a_BiomeMap); } @@ -180,7 +180,7 @@ int cChunkGenerator::GetQueueLength(void) EMCSBiome cChunkGenerator::GetBiomeAt(int a_BlockX, int a_BlockZ) { - ASSERT(m_Generator != NULL); + ASSERT(m_Generator != nullptr); return m_Generator->GetBiomeAt(a_BlockX, a_BlockZ); } @@ -283,8 +283,8 @@ void cChunkGenerator::Execute(void) void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ) { - ASSERT(m_PluginInterface != NULL); - ASSERT(m_ChunkSink != NULL); + ASSERT(m_PluginInterface != nullptr); + ASSERT(m_ChunkSink != nullptr); ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ)); cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ); diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 0105fdb70..2c88f23f1 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -687,9 +687,9 @@ cCompoGenCache::cCompoGenCache(cTerrainCompositionGenPtr a_Underlying, int a_Cac cCompoGenCache::~cCompoGenCache() { delete[] m_CacheData; - m_CacheData = NULL; + m_CacheData = nullptr; delete[] m_CacheOrder; - m_CacheOrder = NULL; + m_CacheOrder = nullptr; } diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 358d97c92..625dffa84 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -48,7 +48,7 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile CompoGenName = "Biomal"; } - cTerrainCompositionGen * res = NULL; + cTerrainCompositionGen * res = nullptr; if (NoCaseCompare(CompoGenName, "sameblock") == 0) { res = new cCompoGenSameBlock; @@ -102,7 +102,7 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed); } - ASSERT(res != NULL); + ASSERT(res != nullptr); // Read the settings from the ini file: res->InitializeCompoGen(a_IniFile); @@ -145,7 +145,7 @@ void cComposableGenerator::Initialize(cIniFile & a_IniFile) void cComposableGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) { - if (m_BiomeGen != NULL) // Quick fix for generator deinitializing before the world storage finishes loading + if (m_BiomeGen != nullptr) // Quick fix for generator deinitializing before the world storage finishes loading { m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, a_BiomeMap); } diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 93fe8b472..3f328868d 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -198,7 +198,7 @@ protected: } ; cChestEntity * ChestEntity = (cChestEntity *)a_ChunkDesc.GetBlockEntity(RelX, m_FloorHeight + 1, RelZ); - ASSERT((ChestEntity != NULL) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST)); + ASSERT((ChestEntity != nullptr) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST)); cNoise Noise(a_ChunkDesc.GetChunkX() ^ a_ChunkDesc.GetChunkZ()); int NumSlots = 3 + ((Noise.IntNoise3DInt(a_Chest.x, a_Chest.y, a_Chest.z) / 11) % 4); int Seed = Noise.IntNoise2DInt(RelX, RelZ); diff --git a/src/Generating/GridStructGen.cpp b/src/Generating/GridStructGen.cpp index 7090f14b1..3c08c1a39 100644 --- a/src/Generating/GridStructGen.cpp +++ b/src/Generating/GridStructGen.cpp @@ -135,7 +135,7 @@ void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructur int OriginX = GridX + ((m_Noise.IntNoise2DInt(GridX + 3, GridZ + 5) / 7) % (m_MaxOffsetX * 2)) - m_MaxOffsetX; int OriginZ = GridZ + ((m_Noise.IntNoise2DInt(GridX + 5, GridZ + 3) / 7) % (m_MaxOffsetZ * 2)) - m_MaxOffsetZ; cStructurePtr Structure = CreateStructure(GridX, GridZ, OriginX, OriginZ); - if (Structure.get() == NULL) + if (Structure.get() == nullptr) { Structure.reset(new cEmptyStructure(GridX, GridZ, OriginX, OriginZ)); } diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index b7d4b337c..acfefaefc 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -29,7 +29,7 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB } a_CacheOffByDefault = false; - cTerrainHeightGen * res = NULL; + cTerrainHeightGen * res = nullptr; if (NoCaseCompare(HeightGenName, "flat") == 0) { res = new cHeiGenFlat; @@ -142,9 +142,9 @@ cHeiGenCache::cHeiGenCache(cTerrainHeightGenPtr a_HeiGenToCache, int a_CacheSize cHeiGenCache::~cHeiGenCache() { delete[] m_CacheData; - m_CacheData = NULL; + m_CacheData = nullptr; delete[] m_CacheOrder; - m_CacheOrder = NULL; + m_CacheOrder = nullptr; } diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp index 0532aff39..55b3b64dd 100644 --- a/src/Generating/MineShafts.cpp +++ b/src/Generating/MineShafts.cpp @@ -112,7 +112,7 @@ class cMineShaftCorridor : public: /** Creates a new Corridor attached to the specified pivot point and direction. Checks all ParentSystem's objects and disallows intersecting. Initializes the new object to fit. - May return NULL if cannot fit. + May return nullptr if cannot fit. */ static cMineShaft * CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, @@ -165,7 +165,7 @@ class cMineShaftCrossing : public: /** Creates a new Crossing attached to the specified pivot point and direction. Checks all ParentSystem's objects and disallows intersecting. Initializes the new object to fit. - May return NULL if cannot fit. + May return nullptr if cannot fit. */ static cMineShaft * CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, @@ -199,7 +199,7 @@ public: /** Creates a new Staircase attached to the specified pivot point and direction. Checks all ParentSystem's objects and disallows intersecting. Initializes the new object to fit. - May return NULL if cannot fit. + May return nullptr if cannot fit. */ static cMineShaft * CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, @@ -351,7 +351,7 @@ void cStructGenMineShafts::cMineShaftSystem::AppendBranch( return; } - cMineShaft * Next = NULL; + cMineShaft * Next = nullptr; int rnd = (a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + a_RecursionLevel * 16, a_PivotZ) / 13) % m_ProbLevelStaircase; if (rnd < m_ProbLevelCorridor) { @@ -365,7 +365,7 @@ void cStructGenMineShafts::cMineShaftSystem::AppendBranch( { Next = cMineShaftStaircase::CreateAndFit(*this, a_PivotX, a_PivotY, a_PivotZ, a_Direction, a_Noise); } - if (Next == NULL) + if (Next == nullptr) { return; } @@ -552,7 +552,7 @@ cMineShaft * cMineShaftCorridor::CreateAndFit( } if (!a_ParentSystem.CanAppend(BoundingBox)) { - return NULL; + return nullptr; } return new cMineShaftCorridor(a_ParentSystem, BoundingBox, NumSegments, a_Direction, a_Noise); } @@ -796,7 +796,7 @@ void cMineShaftCorridor::PlaceChest(cChunkDesc & a_ChunkDesc) { a_ChunkDesc.SetBlockTypeMeta(x, m_BoundingBox.p1.y + 1, z, E_BLOCK_CHEST, Meta); cChestEntity * ChestEntity = (cChestEntity *)a_ChunkDesc.GetBlockEntity(x, m_BoundingBox.p1.y + 1, z); - ASSERT((ChestEntity != NULL) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST)); + ASSERT((ChestEntity != nullptr) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST)); cNoise Noise(a_ChunkDesc.GetChunkX() ^ a_ChunkDesc.GetChunkZ()); int NumSlots = 3 + ((Noise.IntNoise3DInt(x, m_BoundingBox.p1.y, z) / 11) % 4); int Seed = Noise.IntNoise2DInt(x, z); @@ -1006,7 +1006,7 @@ cMineShaft * cMineShaftCrossing::CreateAndFit( } if (!a_ParentSystem.CanAppend(BoundingBox)) { - return NULL; + return nullptr; } return new cMineShaftCrossing(a_ParentSystem, BoundingBox); } @@ -1157,7 +1157,7 @@ cMineShaft * cMineShaftStaircase::CreateAndFit( } if (!a_ParentSystem.CanAppend(Box)) { - return NULL; + return nullptr; } return new cMineShaftStaircase(a_ParentSystem, Box, a_Direction, Slope); } diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp index ae4b6e36c..97aa646fc 100644 --- a/src/Generating/PieceGenerator.cpp +++ b/src/Generating/PieceGenerator.cpp @@ -289,7 +289,7 @@ cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece m_NumCCWRotations(a_NumCCWRotations), m_HasBeenMovedToGround(false) { - m_Depth = (m_Parent == NULL) ? 0 : (m_Parent->GetDepth() + 1); + m_Depth = (m_Parent == nullptr) ? 0 : (m_Parent->GetDepth() + 1); m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z); m_HitBox.Sort(); } @@ -402,7 +402,7 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, i } int Rotation = Rotations[rnd % NumRotations]; - cPlacedPiece * res = new cPlacedPiece(NULL, *StartingPiece, Vector3i(a_BlockX, a_BlockY, a_BlockZ), Rotation); + cPlacedPiece * res = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, a_BlockY, a_BlockZ), Rotation); // Place the piece's connectors into a_OutConnectors: const cPiece::cConnectors & Conn = StartingPiece->GetConnectors(); diff --git a/src/Generating/Prefab.cpp b/src/Generating/Prefab.cpp index 6da3c3d10..761986690 100644 --- a/src/Generating/Prefab.cpp +++ b/src/Generating/Prefab.cpp @@ -328,7 +328,7 @@ void cPrefab::AddConnector(int a_RelX, int a_RelY, int a_RelZ, eBlockFace a_Dire void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef) { - ASSERT(a_CharMapDef != NULL); + ASSERT(a_CharMapDef != nullptr); // Initialize the charmap to all-invalid values: for (size_t i = 0; i < ARRAYCOUNT(a_CharMapOut); i++) @@ -389,7 +389,7 @@ void cPrefab::ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockIma void cPrefab::ParseConnectors(const char * a_ConnectorsDef) { - ASSERT(a_ConnectorsDef != NULL); + ASSERT(a_ConnectorsDef != nullptr); AStringVector Lines = StringSplitAndTrim(a_ConnectorsDef, "\n"); for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) @@ -436,7 +436,7 @@ void cPrefab::ParseConnectors(const char * a_ConnectorsDef) void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef) { // The member needn't be defined at all, if so, skip: - if (a_DepthWeightDef == NULL) + if (a_DepthWeightDef == nullptr) { return; } diff --git a/src/Generating/PrefabPiecePool.cpp b/src/Generating/PrefabPiecePool.cpp index 122b9d2af..895555ef8 100644 --- a/src/Generating/PrefabPiecePool.cpp +++ b/src/Generating/PrefabPiecePool.cpp @@ -16,7 +16,7 @@ cPrefabPiecePool::cPrefabPiecePool( ) { AddPieceDefs(a_PieceDefs, a_NumPieceDefs); - if (a_StartingPieceDefs != NULL) + if (a_StartingPieceDefs != nullptr) { AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs); } @@ -56,7 +56,7 @@ void cPrefabPiecePool::Clear(void) void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs) { - ASSERT(a_PieceDefs != NULL); + ASSERT(a_PieceDefs != nullptr); for (size_t i = 0; i < a_NumPieceDefs; i++) { cPrefab * Prefab = new cPrefab(a_PieceDefs[i]); @@ -71,7 +71,7 @@ void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_ void cPrefabPiecePool::AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs) { - ASSERT(a_StartingPieceDefs != NULL); + ASSERT(a_StartingPieceDefs != nullptr); for (size_t i = 0; i < a_NumStartingPieceDefs; i++) { cPrefab * Prefab = new cPrefab(a_StartingPieceDefs[i]); diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index 1806fd427..a9b359b6a 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -385,7 +385,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_GridX, int a_Gr // Check if all the biomes are village-friendly: // If just one is not, no village is created, because it's likely that an unfriendly biome is too close - cVillagePiecePool * VillagePrefabs = NULL; + cVillagePiecePool * VillagePrefabs = nullptr; BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; BLOCKTYPE WaterRoadBlock = E_BLOCK_PLANKS; int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; @@ -432,7 +432,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_GridX, int a_Gr } // Create a village based on the chosen prefabs: - if (VillagePrefabs == NULL) + if (VillagePrefabs == nullptr) { return cStructurePtr(); } -- cgit v1.2.3 From 7e1d603080146047bade80ee70982dbe569cdf30 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 26 Oct 2014 19:58:16 +0100 Subject: Added new biomegen: Grown --- src/Generating/BioGen.cpp | 93 +++++ src/Generating/IntGen.h | 954 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1047 insertions(+) create mode 100644 src/Generating/IntGen.h (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 203faff56..c9405040f 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "BioGen.h" +#include "IntGen.h" #include "../IniFile.h" #include "../LinearUpscale.h" @@ -916,6 +917,94 @@ void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile) +//////////////////////////////////////////////////////////////////////////////// +// cBioGenGrown: + +class cBioGenGrown: + public cBiomeGen +{ +public: + cBioGenGrown(int a_Seed) + { + auto FinalRivers = + std::make_shared> (a_Seed + 1, + std::make_shared> (a_Seed + 2, + std::make_shared> (a_Seed + 3, + std::make_shared> (a_Seed + 4, + std::make_shared> (a_Seed + 5, + std::make_shared> (a_Seed + 6, + std::make_shared> (a_Seed + 7, + std::make_shared> (a_Seed + 8, + std::make_shared> (a_Seed + 9, + std::make_shared> (a_Seed + 10, + std::make_shared> (a_Seed + 11, + std::make_shared>(a_Seed + 12 + )))))))))))); + + auto FinalBiomes = + std::make_shared> (a_Seed + 1008, + std::make_shared>(a_Seed + 15, + std::make_shared> (a_Seed + 1000, + std::make_shared> (a_Seed + 16, + std::make_shared> (a_Seed + 1001, + std::make_shared> (a_Seed, + std::make_shared> (a_Seed + 1002, + std::make_shared> (a_Seed + 1, + std::make_shared> ( + std::make_shared> (a_Seed + 1002, + std::make_shared>(a_Seed + 2, + std::make_shared> (a_Seed + 3, + std::make_shared> (a_Seed + 2004, 10, + std::make_shared> (a_Seed + 4, + std::make_shared> (a_Seed + 9, 50, biMushroomIsland, + std::make_shared> (a_Seed + 8, + std::make_shared> (a_Seed + 10, 500, biDeepOcean, + std::make_shared> (a_Seed + 3000, + std::make_shared> (a_Seed + 5, + std::make_shared> ( + std::make_shared> (a_Seed + 1003, + std::make_shared> (a_Seed + 7, + std::make_shared> (bgJungle, bgTemperate, 50, a_Seed + 100, + std::make_shared> (bgIce, bgTemperate, 50, a_Seed + 101, + std::make_shared> (a_Seed + 2000, 70, + std::make_shared> (a_Seed + 1004, + std::make_shared> (a_Seed + 10, + std::make_shared> (a_Seed + 2003, 50, + std::make_shared> (a_Seed + 11, + std::make_shared> (a_Seed + 100, 65 + )))))))))))))))))))))))))))))); + + m_Gen = + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, + std::make_shared> ( + FinalBiomes, FinalRivers + ))))); + } + + virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override + { + cIntGen<16, 16>::Values vals; + m_Gen->GetInts(a_ChunkX * cChunkDef::Width, a_ChunkZ * cChunkDef::Width, vals); + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + cChunkDef::SetBiome(a_Biomes, x, z, (EMCSBiome)vals[x + cChunkDef::Width * z]); + } + } + } + +protected: + cIntGenPtr<16, 16> m_Gen; +}; + + + + + //////////////////////////////////////////////////////////////////////////////// // cBiomeGen: @@ -952,6 +1041,10 @@ cBiomeGenPtr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & { res = new cBioGenTwoLevel(a_Seed); } + else if (NoCaseCompare(BiomeGenName, "grown") == 0) + { + res = new cBioGenGrown(a_Seed); + } else { if (NoCaseCompare(BiomeGenName, "multistepmap") != 0) diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h new file mode 100644 index 000000000..ae940232f --- /dev/null +++ b/src/Generating/IntGen.h @@ -0,0 +1,954 @@ + +// IntGen.h + +// Declares the cIntGen class and descendants for generating and filtering various 2D arrays of ints + +/* +The integers generated may be interpreted in several ways: +- land/see designators + - 0 = ocean + - >0 = land +- biome group designators + - 0 = ocean + - 1 = desert biomes + - 2 = temperate biomes + - 3 = mountains (hills and forests) + - 4 = jungle + - 5 = ice biomes +- biome IDs +The interpretation depends on the generator used and on the position in the chain. + +The generators can be chained together - one produces data that another one consumes. +Some of such chain connections require changing the data dimensions between the two, which is handled automatically +by using templates. +*/ + + + + + +#pragma once + +#include "../BiomeDef.h" + + + + + +/** Constants representing the biome group designators. */ +const int bgOcean = 0; +const int bgDesert = 1; +const int bgTemperate = 2; +const int bgMountains = 3; +const int bgJungle = 4; +const int bgIce = 5; +const int bgMax = 5; // Maximum biome group value + + + + + +/** Interface that all the generator classes provide. */ +template +class cIntGen +{ +public: + /** Holds the array of values generated by this class (descendant). */ + typedef int Values[SizeX * SizeZ]; + + /** Generates the array of templated size into a_Values, based on given min coords. */ + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) = 0; +}; + +template +using cIntGenPtr = std::shared_ptr>; + + + + + + +/** Provides additional cNoise member and its helper functions. */ +template +class cIntGenWithNoise : + public cIntGen +{ + typedef cIntGen super; + +public: + cIntGenWithNoise(int a_Seed) : + m_Noise(a_Seed) + { + } + +protected: + cNoise m_Noise; + + /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ + int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) + { + int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; + return ((rnd & 1) == 0) ? a_Val1 : a_Val2; + } + + /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ + int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) + { + int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; + switch (rnd % 4) + { + case 0: return a_Val1; + case 1: return a_Val2; + case 2: return a_Val3; + default: return a_Val4; + } + } +}; + + + + + + +/** Generates a 2D array of random integers in the specified range [0 .. Range). */ +template +class cIntGenChoice : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + cIntGenChoice(int a_Seed) : + super(a_Seed) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + for (int z = 0; z < SizeZ; z++) + { + int BaseZ = a_MinZ + z; + for (int x = 0; x < SizeX; x++) + { + a_Values[x + SizeX * z] = (m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % Range; + } + } // for z + } +}; + + + + + + +/** Decides between the ocean and landmass biomes. +Has a threshold (in percent) of how much land, the larger the threshold, the more land. +Generates 0 for ocean, biome group ID for landmass. */ +template +class cIntLandOcean : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + cIntLandOcean(int a_Seed, int a_Threshold) : + super(a_Seed), + m_Threshold(a_Threshold) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + for (int z = 0; z < SizeZ; z++) + { + int BaseZ = a_MinZ + z; + for (int x = 0; x < SizeX; x++) + { + int rnd = (m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); + a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgMax + 1) : 0; + } + } + } + +protected: + int m_Threshold; +}; + + + + + +template +class cIntGenZoom : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +protected: + static const int m_LowerSizeX = (SizeX / 2) + 2; + static const int m_LowerSizeZ = (SizeZ / 2) + 2; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenZoom(int a_Seed, Underlying a_UnderlyingGen) : + super(a_Seed), + m_UnderlyingGen(a_UnderlyingGen) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Generate the underlying data with half the resolution: + int lowerMinX = a_MinX >> 1; + int lowerMinZ = a_MinZ >> 1; + int Underlying[m_LowerSizeX * m_LowerSizeZ]; + m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, Underlying); + const int lowStepX = (m_LowerSizeX - 1) * 2; + const int lowStepZ = (m_LowerSizeZ - 1) * 2; + int Cache[lowStepX * lowStepZ]; + + // Discreet-interpolate the values into twice the size: + for (int z = 0; z < m_LowerSizeZ - 1; ++z) + { + int idx = (z * 2) * lowStepX; + int PrevZ0 = Underlying[z * m_LowerSizeX]; + int PrevZ1 = Underlying[(z + 1) * m_LowerSizeX]; + + for (int x = 0; x < m_LowerSizeX - 1; ++x) + { + int ValX1Z0 = Underlying[x + 1 + z * m_LowerSizeX]; + int ValX1Z1 = Underlying[x + 1 + (z + 1) * m_LowerSizeX]; + int RndX = (x + lowerMinX) * 2; + int RndZ = (z + lowerMinZ) * 2; + Cache[idx] = PrevZ0; + Cache[idx + lowStepX] = ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); + idx++; + Cache[idx] = ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); + Cache[idx + lowStepX] = ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx++; + PrevZ0 = ValX1Z0; + PrevZ1 = ValX1Z1; + } + } + + // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: + for (int z = 0; z < SizeZ; ++z) + { + memcpy(a_Values + z * SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int)); + } + } + +protected: + Underlying m_UnderlyingGen; +}; + + + + + +template +class cIntGenSmooth : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + static const int m_UnderlyingSizeX = SizeX + 2; + static const int m_UnderlyingSizeZ = SizeZ + 2; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenSmooth(int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Generate the underlying values: + int Cache[(SizeX + 2) * (SizeZ + 2)]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + + // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. + // Also get rid of single-pixel irregularities (A-B-A): + for (int z = 0; z < SizeZ; z++) + { + int NoiseZ = a_MinZ + z; + for (int x = 0; x < SizeX; x++) + { + int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; + int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; + int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; + + if ((Left == Right) && (Above == Below)) + { + if (((m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) + { + val = Left; + } + else + { + val = Above; + } + } + else + { + if (Left == Right) + { + val = Left; + } + + if (Above == Below) + { + val = Above; + } + } + + a_Values[x + z * SizeX] = val; + } + } + } + +protected: + Underlying m_Underlying; +}; + + + + + +template +class cIntGenBeaches : + public cIntGen +{ + typedef cIntGen super; + static const int m_UnderlyingSizeX = SizeX + 2; + static const int m_UnderlyingSizeZ = SizeZ + 2; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenBeaches(Underlying a_Underlying) : + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Map for biome -> its beach: + static const int ToBeach[] = + { + /* biOcean */ biOcean, + /* biPlains */ biBeach, + /* biDesert */ biBeach, + /* biExtremeHills */ biStoneBeach, + /* biForest */ biBeach, + /* biTaiga */ biColdBeach, + /* biSwampland */ biSwampland, + /* biRiver */ biRiver, + /* biNether */ biNether, + /* biEnd */ biEnd, + /* biFrozenOcean */ biColdBeach, + /* biFrozenRiver */ biColdBeach, + /* biIcePlains */ biColdBeach, + /* biIceMountains */ biColdBeach, + /* biMushroomIsland */ biMushroomShore, + /* biMushroomShore */ biMushroomShore, + /* biBeach */ biBeach, + /* biDesertHills */ biBeach, + /* biForestHills */ biBeach, + /* biTaigaHills */ biColdBeach, + /* biExtremeHillsEdge */ biStoneBeach, + /* biJungle */ biBeach, + /* biJungleHills */ biBeach, + /* biJungleEdge */ biBeach, + /* biDeepOcean */ biOcean, + /* biStoneBeach */ biStoneBeach, + /* biColdBeach */ biColdBeach, + /* biBirchForest */ biBeach, + /* biBirchForestHills */ biBeach, + /* biRoofedForest */ biBeach, + /* biColdTaiga */ biColdBeach, + /* biColdTaigaHills */ biColdBeach, + /* biMegaTaiga */ biStoneBeach, + /* biMegaTaigaHills */ biStoneBeach, + /* biExtremeHillsPlus */ biStoneBeach, + /* biSavanna */ biBeach, + /* biSavannaPlateau */ biBeach, + /* biMesa */ biMesa, + /* biMesaPlateauF */ biMesa, + /* biMesaPlateau */ biMesa, + }; + + // Generate the underlying values: + int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + + // Add beaches between ocean and biomes: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; + int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; + int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; + if (!IsBiomeOcean(val)) + { + if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + { + val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; + } + } + a_Values[x + z * SizeX] = val; + } + } + } + +protected: + Underlying m_Underlying; +}; + + + + + +/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +template +class cIntGenAddIslands : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + super(a_Seed), + m_Threshold(a_Threshold), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + if (a_Values[x + z * SizeX] == 0) + { + int rnd = m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; + if (rnd % 100 < m_Threshold) + { + a_Values[x + z * SizeX] = (rnd / 100) % 4; + } + } + } + } + } + +protected: + int m_Threshold; + + Underlying m_Underlying; +}; + + + + + +/** A filter that adds an edge biome group between two biome groups that need an edge between them. */ +template +class cIntGenBiomeGroupEdges : + public cIntGen +{ + typedef cIntGen super; + + static const int m_UnderlyingSizeX = SizeX + 2; + static const int m_UnderlyingSizeZ = SizeZ + 2; + +public: + + typedef cIntGenPtr Underlying; + + cIntGenBiomeGroupEdges(Underlying a_Underlying) : + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) + { + // Generate the underlying biome groups: + int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX, a_MinZ, Cache); + + // Change the biomes on incompatible edges into an edge biome: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int v = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; + int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; + int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; + switch (v) + { + // Oceans don't need any edges: + case bgOcean: + { + v = bgOcean; + break; + } + + // Desert should neighbor only oceans, desert and temperates; change to temperate when another: + case bgDesert: + { + if ( + !IsDesertCompatible(Above) || + !IsDesertCompatible(Below) || + !IsDesertCompatible(Left) || + !IsDesertCompatible(Right) + ) + { + v = bgTemperate; + } + break; + } + + // Ice should not neighbor deserts; change to temperate: + case bgIce: + { + if ( + (Above == bgDesert) || + (Below == bgDesert) || + (Left == bgDesert) || + (Right == bgDesert) + ) + { + v = bgTemperate; + } + break; + } + + // Jungle should not neighbor Desert or Ice; change to temperate: + case bgJungle: + { + if ( + !IsJungleCompatible(Above) || + !IsJungleCompatible(Below) || + !IsJungleCompatible(Left) || + !IsJungleCompatible(Right) + ) + { + v = bgTemperate; + } + } + } + a_Values[x + z * SizeX] = v; + } // for x + } // for z + } + +protected: + Underlying m_Underlying; + + + inline bool IsDesertCompatible(int a_BiomeGroup) + { + return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert) || (a_BiomeGroup == bgTemperate)); + } + + inline bool IsJungleCompatible(int a_BiomeGroup) + { + return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgIce)); + } +}; + + + + + +template +class cIntGenBiomes : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenBiomes(int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Define the per-biome-group biomes: + static const int OceanBiomes[] = + { + biOcean, // biDeepOcean, + }; + + static const int DesertBiomes[] = + { + biDesert, biDesert, biSavanna, biPlains, + }; + + static const int TemperateBiomes[] = + { + biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, + }; + + static const int MountainBiomes[] = + { + biExtremeHills, biForest, biTaiga, biPlains, + }; + + static const int JungleBiomes[] = + { + biJungle, biJungle, biForest, + }; + + static const int IceBiomes[] = + { + biIcePlains, biIcePlains, biColdTaiga, + }; + + static const cBiomesInGroups BiomesInGroups[] = + { + { static_cast(ARRAYCOUNT(OceanBiomes)), OceanBiomes}, + { static_cast(ARRAYCOUNT(DesertBiomes)), DesertBiomes}, + { static_cast(ARRAYCOUNT(TemperateBiomes)), TemperateBiomes}, + { static_cast(ARRAYCOUNT(MountainBiomes)), MountainBiomes}, + { static_cast(ARRAYCOUNT(JungleBiomes)), JungleBiomes}, + { static_cast(ARRAYCOUNT(IceBiomes)), IceBiomes}, + }; + + // Generate the underlying values, representing biome groups: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + + // Overwrite each biome group with a random biome from that group: + for (int z = 0; z < SizeZ; z++) + { + int IdxZ = z * SizeX; + for (int x = 0; x < SizeX; x++) + { + int val = a_Values[x + IdxZ]; + const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + int rnd = (m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); + a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; + } + } + } + +protected: + + struct cBiomesInGroups + { + const int Count; + const int * Biomes; + }; + + + /** The underlying int generator */ + Underlying m_Underlying; +}; + + + + + +template +class cIntGenReplaceRandomly : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_From(a_From), + m_To(a_To), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Generate the underlying values: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + + // Replace some of the values: + for (int z = 0; z < SizeZ; z++) + { + int idxZ = z * SizeX; + for (int x = 0; x < SizeX; x++) + { + int idx = x + idxZ; + if (a_Values[idx] == m_From) + { + int rnd = m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 100 < m_Chance) + { + a_Values[idx] = m_To; + } + } + } + } // for z + } + + +protected: + int m_From; + int m_To; + int m_Chance; + Underlying m_Underlying; +}; + + + + + +/** Mixer that joins together finalized biomes and rivers. +It first checks for oceans; if there's no ocean, it checks for a river. */ +template +class cIntGenMixRivers: + public cIntGen +{ + typedef cIntGen super; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers): + m_Biomes(a_Biomes), + m_Rivers(a_Rivers) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Generate the underlying data: + m_Biomes->GetInts(a_MinX, a_MinZ, a_Values); + Values Rivers; + m_Rivers->GetInts(a_MinX, a_MinZ, Rivers); + + // Mix the values: + for (int z = 0; z < SizeZ; z++) + { + int idxZ = z * SizeX; + for (int x = 0; x < SizeX; x++) + { + int idx = x + idxZ; + if (IsBiomeOcean(a_Values[idx])) + { + // Oceans are kept without any changes + continue; + } + if (Rivers[idx] != biRiver) + { + // There's no river, keep the current value + continue; + } + + // There's a river, change the output to a river or a frozen river, based on the original biome: + if (IsBiomeVeryCold((EMCSBiome)a_Values[idx])) + { + a_Values[idx] = biFrozenRiver; + } + else + { + a_Values[idx] = biRiver; + } + } // for x + } // for z + } + +protected: + Underlying m_Biomes; + Underlying m_Rivers; +}; + + + + + +/** Generates a river based on the underlying data. +This is basically an edge detector over the underlying data. The rivers are the edges where the underlying data +changes from one pixel to its neighbor. */ +template +class cIntGenRiver: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + static const int UnderlyingSizeX = SizeX + 2; + static const int UnderlyingSizeZ = SizeZ + 2; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenRiver(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Generate the underlying data: + int Cache[UnderlyingSizeX * UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + + // Detect the edges: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int Above = Cache[x + 1 + z * UnderlyingSizeX]; + int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; + int Left = Cache[x + (z + 1) * UnderlyingSizeX]; + int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; + int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; + + if ((val == Above) && (val == Below) && (val == Left) && (val == Right)) + { + val = 0; + } + else + { + val = biRiver; + } + a_Values[x + z * SizeX] = val; + } // for x + } // for z + } + +protected: + Underlying m_Underlying; +}; + + + + + +/** Turns some of the oceans into the specified biome. Used for mushroom and deep ocean. +The biome is only placed if at least 3 of its neighbors are ocean and only with the specified chance. */ +template +class cIntGenAddToOcean: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + static const int UnderlyingSizeX = SizeX + 2; + static const int UnderlyingSizeZ = SizeZ + 2; + +public: + typedef cIntGenPtr Underlying; + + + cIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_ToValue(a_ToValue), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + { + // Generate the underlying data: + int Cache[UnderlyingSizeX * UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + + // Add the mushroom islands: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; + if (!IsBiomeOcean(val)) + { + a_Values[x + z * SizeX] = val; + continue; + } + + // Count the ocean neighbors: + int Above = Cache[x + 1 + z * UnderlyingSizeX]; + int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; + int Left = Cache[x + (z + 1) * UnderlyingSizeX]; + int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; + int NumOceanNeighbors = 0; + if (IsBiomeOcean(Above)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Above)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Above)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Above)) + { + NumOceanNeighbors += 1; + } + + // If at least 3 ocean neighbors and the chance is right, change: + if ((NumOceanNeighbors >= 3) && ((m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance)) + { + a_Values[x + z * SizeX] = m_ToValue; + } + else + { + a_Values[x + z * SizeX] = val; + } + } // for x + } // for z + } + +protected: + /** Chance, in permille, of changing the biome. */ + int m_Chance; + + /** The value to change the ocean into. */ + int m_ToValue; + + Underlying m_Underlying; +}; + + + + -- cgit v1.2.3 From dcad6d362685367d996f7acf7c3783f684d269f6 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 26 Oct 2014 20:12:29 +0100 Subject: Added a missing header to CMakeLists. --- src/Generating/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'src/Generating') diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index cd3d5a9f3..afe30533e 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -46,6 +46,7 @@ SET (HDRS FinishGen.h GridStructGen.h HeiGen.h + IntGen.h MineShafts.h NetherFortGen.h Noise3DGenerator.h -- cgit v1.2.3 From dcbe1717cc4e86b3d48c93da9654592ef2373073 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 26 Oct 2014 21:35:24 +0100 Subject: Fixed a copypasta error in cIntGenAddToOcean. --- src/Generating/IntGen.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index ae940232f..a0064715f 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -124,7 +124,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename Values & a_Values) override { for (int z = 0; z < SizeZ; z++) { @@ -913,15 +913,15 @@ public: { NumOceanNeighbors += 1; } - if (IsBiomeOcean(Above)) + if (IsBiomeOcean(Below)) { NumOceanNeighbors += 1; } - if (IsBiomeOcean(Above)) + if (IsBiomeOcean(Left)) { NumOceanNeighbors += 1; } - if (IsBiomeOcean(Above)) + if (IsBiomeOcean(Right)) { NumOceanNeighbors += 1; } -- cgit v1.2.3 From 74df4618de1c52c22f892e0bf82ec612521a10c0 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 26 Oct 2014 22:56:02 +0100 Subject: BioGenGrown: Smaller biomes, add land to map center. --- src/Generating/BioGen.cpp | 6 ++---- src/Generating/IntGen.h | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index c9405040f..fcb4d74ed 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -969,10 +969,8 @@ public: std::make_shared> (a_Seed + 2000, 70, std::make_shared> (a_Seed + 1004, std::make_shared> (a_Seed + 10, - std::make_shared> (a_Seed + 2003, 50, - std::make_shared> (a_Seed + 11, - std::make_shared> (a_Seed + 100, 65 - )))))))))))))))))))))))))))))); + std::make_shared> (a_Seed + 100, 65 + )))))))))))))))))))))))))))); m_Gen = std::make_shared>(a_Seed, diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index a0064715f..1eb20711d 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -124,7 +124,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, typename Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { for (int z = 0; z < SizeZ; z++) { @@ -146,13 +146,13 @@ public: Has a threshold (in percent) of how much land, the larger the threshold, the more land. Generates 0 for ocean, biome group ID for landmass. */ template -class cIntLandOcean : +class cIntGenLandOcean : public cIntGenWithNoise { typedef cIntGenWithNoise super; public: - cIntLandOcean(int a_Seed, int a_Threshold) : + cIntGenLandOcean(int a_Seed, int a_Threshold) : super(a_Seed), m_Threshold(a_Threshold) { @@ -170,6 +170,12 @@ public: a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgMax + 1) : 0; } } + + // If the centerpoint of the world is within the area, set it to bgTemperate, always: + if ((a_MinX <= 0) && (a_MinZ <= 0) && (a_MinX + SizeX > 0) && (a_MinZ + SizeZ > 0)) + { + a_Values[-a_MinX - a_MinZ * SizeX] = bgTemperate; + } } protected: @@ -451,12 +457,12 @@ public: { for (int x = 0; x < SizeX; x++) { - if (a_Values[x + z * SizeX] == 0) + if (a_Values[x + z * SizeX] == bgOcean) { int rnd = m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; if (rnd % 100 < m_Threshold) { - a_Values[x + z * SizeX] = (rnd / 100) % 4; + a_Values[x + z * SizeX] = (rnd / 100) % bgMax; } } } @@ -511,13 +517,6 @@ public: int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; switch (v) { - // Oceans don't need any edges: - case bgOcean: - { - v = bgOcean; - break; - } - // Desert should neighbor only oceans, desert and temperates; change to temperate when another: case bgDesert: { -- cgit v1.2.3 From 7d6db6f33d60a7976e714478ec27e65faa79a46b Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 26 Oct 2014 22:59:59 +0100 Subject: IntGen: Attempt at fixing Linux compilation. --- src/Generating/IntGen.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 1eb20711d..20927f7fb 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -131,7 +131,7 @@ public: int BaseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { - a_Values[x + SizeX * z] = (m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % Range; + a_Values[x + SizeX * z] = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % Range; } } // for z } @@ -159,7 +159,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { for (int z = 0; z < SizeZ; z++) { @@ -207,7 +207,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying data with half the resolution: int lowerMinX = a_MinX >> 1; @@ -276,7 +276,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying values: int Cache[(SizeX + 2) * (SizeZ + 2)]; @@ -350,7 +350,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Map for biome -> its beach: static const int ToBeach[] = @@ -450,7 +450,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); for (int z = 0; z < SizeZ; z++) @@ -499,7 +499,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) { // Generate the underlying biome groups: int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; @@ -602,7 +602,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Define the per-biome-group biomes: static const int OceanBiomes[] = @@ -699,7 +699,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying values: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); @@ -754,11 +754,11 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying data: m_Biomes->GetInts(a_MinX, a_MinZ, a_Values); - Values Rivers; + typename super::Values Rivers; m_Rivers->GetInts(a_MinX, a_MinZ, Rivers); // Mix the values: @@ -823,7 +823,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying data: int Cache[UnderlyingSizeX * UnderlyingSizeZ]; @@ -884,7 +884,7 @@ public: } - virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) override + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying data: int Cache[UnderlyingSizeX * UnderlyingSizeZ]; -- cgit v1.2.3 From 7d08d34693706ef70cff6cfc796d4f7cbd396bc5 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 27 Oct 2014 09:35:21 +0100 Subject: Removed too advanced C++11 features. We need to keep gcc 4.6 compatibility; these features were not implemented in that version yet. --- src/Generating/BioGen.cpp | 2 +- src/Generating/IntGen.h | 58 ++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 32 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index fcb4d74ed..96c181915 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -996,7 +996,7 @@ public: } protected: - cIntGenPtr<16, 16> m_Gen; + std::shared_ptr> m_Gen; }; diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 20927f7fb..94a17abd9 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -60,10 +60,6 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) = 0; }; -template -using cIntGenPtr = std::shared_ptr>; - - @@ -166,7 +162,7 @@ public: int BaseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { - int rnd = (m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); + int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgMax + 1) : 0; } } @@ -197,7 +193,7 @@ protected: static const int m_LowerSizeZ = (SizeZ / 2) + 2; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenZoom(int a_Seed, Underlying a_UnderlyingGen) : @@ -232,10 +228,10 @@ public: int RndX = (x + lowerMinX) * 2; int RndZ = (z + lowerMinZ) * 2; Cache[idx] = PrevZ0; - Cache[idx + lowStepX] = ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); + Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); idx++; - Cache[idx] = ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); - Cache[idx + lowStepX] = ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); + Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); idx++; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; @@ -262,11 +258,11 @@ class cIntGenSmooth : public cIntGenWithNoise { typedef cIntGenWithNoise super; - static const int m_UnderlyingSizeX = SizeX + 2; - static const int m_UnderlyingSizeZ = SizeZ + 2; + static const int UnderlyingSizeX = SizeX + 2; + static const int UnderlyingSizeZ = SizeZ + 2; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenSmooth(int a_Seed, Underlying a_Underlying) : @@ -279,7 +275,7 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying values: - int Cache[(SizeX + 2) * (SizeZ + 2)]; + int Cache[UnderlyingSizeX * UnderlyingSizeZ]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. @@ -289,15 +285,15 @@ public: int NoiseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { - int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; - int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; + int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; + int Above = Cache[x + 1 + z * UnderlyingSizeX]; + int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; + int Left = Cache[x + (z + 1) * UnderlyingSizeX]; + int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; if ((Left == Right) && (Above == Below)) { - if (((m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) + if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) { val = Left; } @@ -341,7 +337,7 @@ class cIntGenBeaches : static const int m_UnderlyingSizeZ = SizeZ + 2; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenBeaches(Underlying a_Underlying) : @@ -439,7 +435,7 @@ class cIntGenAddIslands : typedef cIntGenWithNoise super; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : @@ -459,7 +455,7 @@ public: { if (a_Values[x + z * SizeX] == bgOcean) { - int rnd = m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; + int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; if (rnd % 100 < m_Threshold) { a_Values[x + z * SizeX] = (rnd / 100) % bgMax; @@ -491,7 +487,7 @@ class cIntGenBiomeGroupEdges : public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenBiomeGroupEdges(Underlying a_Underlying) : m_Underlying(a_Underlying) @@ -592,7 +588,7 @@ class cIntGenBiomes : typedef cIntGenWithNoise super; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenBiomes(int a_Seed, Underlying a_Underlying) : @@ -656,7 +652,7 @@ public: { int val = a_Values[x + IdxZ]; const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; - int rnd = (m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); + int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } } @@ -686,7 +682,7 @@ class cIntGenReplaceRandomly : typedef cIntGenWithNoise super; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) : @@ -713,7 +709,7 @@ public: int idx = x + idxZ; if (a_Values[idx] == m_From) { - int rnd = m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; if (rnd % 100 < m_Chance) { a_Values[idx] = m_To; @@ -744,7 +740,7 @@ class cIntGenMixRivers: typedef cIntGen super; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers): @@ -813,7 +809,7 @@ class cIntGenRiver: static const int UnderlyingSizeZ = SizeZ + 2; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenRiver(int a_Seed, Underlying a_Underlying): @@ -872,7 +868,7 @@ class cIntGenAddToOcean: static const int UnderlyingSizeZ = SizeZ + 2; public: - typedef cIntGenPtr Underlying; + typedef std::shared_ptr> Underlying; cIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): @@ -926,7 +922,7 @@ public: } // If at least 3 ocean neighbors and the chance is right, change: - if ((NumOceanNeighbors >= 3) && ((m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance)) + if ((NumOceanNeighbors >= 3) && ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance)) { a_Values[x + z * SizeX] = m_ToValue; } -- cgit v1.2.3 From a068ebf3e022f72ae703b762215abb5039cd35c8 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 27 Oct 2014 09:48:57 +0100 Subject: cIntGen: Added a virtual destructor. --- src/Generating/IntGen.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 94a17abd9..d7ed9275a 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -53,6 +53,10 @@ template class cIntGen { public: + /** Force a virtual destructor in all descendants. + Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */ + virtual ~cIntGen() {} + /** Holds the array of values generated by this class (descendant). */ typedef int Values[SizeX * SizeZ]; -- cgit v1.2.3 From 8a443c028f6c24659b0a65ff709c8b5f01fd6f5a Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 17:11:31 +0000 Subject: Test warning fix. --- src/Generating/DistortedHeightmap.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index aac1d2bf3..d6474b3ca 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -270,6 +270,17 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = /* biMesaBryce */ { 0.5f, 0.5f}, // 165 /* biMesaPlateauFM */ { 2.0f, 2.0f}, // 166 /* biMesaPlateauM */ { 2.0f, 2.0f}, // 167 + + // biomes 168 .. 255 are unused, 88 empty placeholders here: + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 168 .. 177 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 178 .. 187 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 188 .. 197 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 198 .. 207 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 208 .. 217 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 218 .. 227 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 228 .. 237 + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 238 .. 247 + {}, {}, {}, {}, {}, {}, {}, {}, // 248 .. 255 } ; -- cgit v1.2.3 From c0a9a83abfb7c161b3d5ed994d6b5bb7bb7a1fb8 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 18:09:34 +0000 Subject: Actually fixed the warning. --- src/Generating/DistortedHeightmap.cpp | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index d6474b3ca..5ece4dce5 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -227,15 +227,15 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = /* 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 + {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 + {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}, // 60 .. 69 + {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}, // 70 .. 79 + {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}, // 80 .. 89 + {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}, // 90 .. 99 + {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 @@ -270,17 +270,6 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = /* biMesaBryce */ { 0.5f, 0.5f}, // 165 /* biMesaPlateauFM */ { 2.0f, 2.0f}, // 166 /* biMesaPlateauM */ { 2.0f, 2.0f}, // 167 - - // biomes 168 .. 255 are unused, 88 empty placeholders here: - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 168 .. 177 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 178 .. 187 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 188 .. 197 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 198 .. 207 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 208 .. 217 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 218 .. 227 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 228 .. 237 - {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 238 .. 247 - {}, {}, {}, {}, {}, {}, {}, {}, // 248 .. 255 } ; -- cgit v1.2.3 From 6e21897bc6404f8e95ab61ea4203e5b2d73b19a3 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 19:49:52 +0000 Subject: Fixed remaining warnings. --- src/Generating/DistortedHeightmap.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index 5ece4dce5..974aabccd 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -246,22 +246,22 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = /* biSwamplandM */ { 0.0f, 0.0f}, // 134 // Biomes 135 .. 139 unused, 5 empty placeholders here: - {}, {}, {}, {}, {}, // 135 .. 139 + {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: - {}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148 + {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 /* biJungleM */ { 4.0f, 4.0f}, // 149 - {}, // 150 + {0.0f,0.0f}, // 150 /* biJungleEdgeM */ { 3.0f, 3.0f}, // 151 - {}, {}, {}, // 152 .. 154 + {0.0f,0.0f}, {0.0f,0.0f}, {0.0f,0.0f}, // 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 + {0.0f,0.0f}, // 159 /* biMegaSpruceTaiga */ { 3.0f, 3.0f}, // 160 /* biMegaSpruceTaigaHills */ { 3.0f, 3.0f}, // 161 /* biExtremeHillsPlusM */ {32.0f, 32.0f}, // 162 -- cgit v1.2.3 From 0cdf262053129cf75c9158f269efa52b29d5b7df Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 19:52:04 +0000 Subject: Fix missing biomes in enum. --- src/Generating/FinishGen.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 0564789dc..6b0bd686c 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -414,6 +414,11 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc) } break; } + default: + { + // There's no snow in the other biomes. + break; + } } } } // for z -- cgit v1.2.3 From 59ca542c28edefc9454dd2be06ca66f5c7a0c18f Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 19:53:16 +0000 Subject: Another switch. --- src/Generating/FinishGen.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 6b0bd686c..18f8ee2bc 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -459,6 +459,11 @@ void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc) } break; } + default: + { + // No icy water in other biomes. + break; + } } } } // for z -- cgit v1.2.3 From 7de8757ac98cff40a5da575d58e40425f2130057 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 20:05:34 +0000 Subject: Fixed more warnings. It's ugly though. --- src/Generating/HeiGen.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index a0b8770f5..0f883f156 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -430,15 +430,15 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] = /* 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 + {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 + {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}, // 60 .. 69 + {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}, // 70 .. 79 + {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}, // 80 .. 89 + {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}, // 90 .. 99 + {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 @@ -448,22 +448,22 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] = /* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134 // Biomes 135 .. 139 unused, 5 empty placeholders here: - {}, {}, {}, {}, {}, // 135 .. 139 + {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: - {}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148 + {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 - {}, // 150 + {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 - {}, {}, {}, // 152 .. 154 + {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}, // 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 + {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0}, // 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 -- cgit v1.2.3 From a4932bbd8b08ed2f5d6de94fcfcc4d10484c45a2 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 21:34:02 +0000 Subject: CheckBasicStyle'd --- src/Generating/DistortedHeightmap.cpp | 28 ++++++++++++++-------------- src/Generating/HeiGen.cpp | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index 974aabccd..7c1ab9997 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -227,15 +227,15 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = /* 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 - {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}, // 60 .. 69 - {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}, // 70 .. 79 - {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}, // 80 .. 89 - {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}, // 90 .. 99 - {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 + {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 + {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}, // 60 .. 69 + {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}, // 70 .. 79 + {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}, // 80 .. 89 + {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}, // 90 .. 99 + {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 @@ -246,22 +246,22 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = /* 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 + {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 + {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 /* biJungleM */ { 4.0f, 4.0f}, // 149 - {0.0f,0.0f}, // 150 + {0.0f, 0.0f}, // 150 /* biJungleEdgeM */ { 3.0f, 3.0f}, // 151 - {0.0f,0.0f}, {0.0f,0.0f}, {0.0f,0.0f}, // 152 .. 154 + {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 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 - {0.0f,0.0f}, // 159 + {0.0f, 0.0f}, // 159 /* biMegaSpruceTaiga */ { 3.0f, 3.0f}, // 160 /* biMegaSpruceTaigaHills */ { 3.0f, 3.0f}, // 161 /* biExtremeHillsPlusM */ {32.0f, 32.0f}, // 162 diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 0f883f156..04154dfec 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -430,15 +430,15 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] = /* 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 - {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}, // 60 .. 69 - {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}, // 70 .. 79 - {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}, // 80 .. 89 - {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}, // 90 .. 99 - {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 + {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 + {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}, // 60 .. 69 + {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}, // 70 .. 79 + {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}, // 80 .. 89 + {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}, // 90 .. 99 + {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 @@ -448,22 +448,22 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] = /* 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 + {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 + {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 + {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 - {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}, // 152 .. 154 + {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}, // 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 - {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0}, // 159 + {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 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 -- cgit v1.2.3 From dbe7c8b1702d4141ae0f9d11b74b3d763b8a08c7 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Mon, 27 Oct 2014 21:38:00 +0000 Subject: Comment alignment. --- src/Generating/DistortedHeightmap.cpp | 8 ++++---- src/Generating/HeiGen.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index 7c1ab9997..d5bc6ab55 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -235,7 +235,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}, // 90 .. 99 {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 + {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 @@ -254,14 +254,14 @@ 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}, // 141 .. 148 /* biJungleM */ { 4.0f, 4.0f}, // 149 - {0.0f, 0.0f}, // 150 + {0.0f, 0.0f}, // 150 /* biJungleEdgeM */ { 3.0f, 3.0f}, // 151 - {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 152 .. 154 + {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 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 - {0.0f, 0.0f}, // 159 + {0.0f, 0.0f}, // 159 /* biMegaSpruceTaiga */ { 3.0f, 3.0f}, // 160 /* biMegaSpruceTaigaHills */ { 3.0f, 3.0f}, // 161 /* biExtremeHillsPlusM */ {32.0f, 32.0f}, // 162 diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 04154dfec..f4e231470 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -438,7 +438,7 @@ 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}, // 90 .. 99 {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 + {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 @@ -456,14 +456,14 @@ 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}, // 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 + {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 - {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}, // 152 .. 154 + {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}, // 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 - {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 159 + {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 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 -- cgit v1.2.3 From f34b1291beb81b4fcf82e155e66f4a43d7caf915 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 29 Oct 2014 15:28:27 +0100 Subject: Grown biomes: made biomes smaller, made beaches smaller. --- src/Generating/BioGen.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 96c181915..6fab1b9d9 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -946,18 +946,15 @@ public: std::make_shared>(a_Seed + 15, std::make_shared> (a_Seed + 1000, std::make_shared> (a_Seed + 16, - std::make_shared> (a_Seed + 1001, - std::make_shared> (a_Seed, - std::make_shared> (a_Seed + 1002, - std::make_shared> (a_Seed + 1, std::make_shared> ( std::make_shared> (a_Seed + 1002, - std::make_shared>(a_Seed + 2, - std::make_shared> (a_Seed + 3, - std::make_shared> (a_Seed + 2004, 10, - std::make_shared> (a_Seed + 4, - std::make_shared> (a_Seed + 9, 50, biMushroomIsland, - std::make_shared> (a_Seed + 8, + std::make_shared>(a_Seed + 1, + std::make_shared> (a_Seed + 1002, + std::make_shared> (a_Seed + 2, + std::make_shared> (a_Seed + 2004, 10, + std::make_shared> (a_Seed + 4, + std::make_shared> (a_Seed + 9, 50, biMushroomIsland, + std::make_shared> (a_Seed + 8, std::make_shared> (a_Seed + 10, 500, biDeepOcean, std::make_shared> (a_Seed + 3000, std::make_shared> (a_Seed + 5, @@ -970,7 +967,7 @@ public: std::make_shared> (a_Seed + 1004, std::make_shared> (a_Seed + 10, std::make_shared> (a_Seed + 100, 65 - )))))))))))))))))))))))))))); + ))))))))))))))))))))))))); m_Gen = std::make_shared>(a_Seed, -- cgit v1.2.3 From 8c04abf9aa749af3b15bc92f517b636c9593109e Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 30 Oct 2014 16:24:35 +0100 Subject: QtBiomeVisualiser: Added a prototyping int generator flavor. This generator is easier to manipulate, since it doesn't require rewriting the sizes in the template parameters. On the other hand, it doesn't optimize so well, so it's a bit slower. --- src/Generating/BioGen.cpp | 124 ++++- src/Generating/CMakeLists.txt | 1 + src/Generating/IntGen.h | 173 +++++-- src/Generating/ProtIntGen.h | 1008 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1253 insertions(+), 53 deletions(-) create mode 100644 src/Generating/ProtIntGen.h (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 6fab1b9d9..f9a0a571b 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "BioGen.h" #include "IntGen.h" +#include "ProtIntGen.h" #include "../IniFile.h" #include "../LinearUpscale.h" @@ -927,9 +928,9 @@ public: cBioGenGrown(int a_Seed) { auto FinalRivers = - std::make_shared> (a_Seed + 1, - std::make_shared> (a_Seed + 2, - std::make_shared> (a_Seed + 3, + std::make_shared> (a_Seed + 1, + std::make_shared> (a_Seed + 3, + std::make_shared> (a_Seed + 2, std::make_shared> (a_Seed + 4, std::make_shared> (a_Seed + 5, std::make_shared> (a_Seed + 6, @@ -942,10 +943,10 @@ public: )))))))))))); auto FinalBiomes = - std::make_shared> (a_Seed + 1008, - std::make_shared>(a_Seed + 15, - std::make_shared> (a_Seed + 1000, - std::make_shared> (a_Seed + 16, + std::make_shared> (a_Seed + 1008, + std::make_shared>(a_Seed + 15, + std::make_shared> (a_Seed + 1000, + std::make_shared> (a_Seed + 16, std::make_shared> ( std::make_shared> (a_Seed + 1002, std::make_shared>(a_Seed + 1, @@ -953,7 +954,8 @@ public: std::make_shared> (a_Seed + 2, std::make_shared> (a_Seed + 2004, 10, std::make_shared> (a_Seed + 4, - std::make_shared> (a_Seed + 9, 50, biMushroomIsland, + std::make_shared> (a_Seed + 9, 10, biMushroomIsland, + std::make_shared> (biIcePlains, biIcePlainsSpikes, 5, a_Seed + 99, std::make_shared> (a_Seed + 8, std::make_shared> (a_Seed + 10, 500, biDeepOcean, std::make_shared> (a_Seed + 3000, @@ -961,22 +963,26 @@ public: std::make_shared> ( std::make_shared> (a_Seed + 1003, std::make_shared> (a_Seed + 7, + std::make_shared> (a_Seed + 8, 50, bgOcean, std::make_shared> (bgJungle, bgTemperate, 50, a_Seed + 100, std::make_shared> (bgIce, bgTemperate, 50, a_Seed + 101, + std::make_shared> (bgDesert, bgMesa, 30, a_Seed + 102, std::make_shared> (a_Seed + 2000, 70, + std::make_shared> (a_Seed + 9, 50, bgOcean, std::make_shared> (a_Seed + 1004, std::make_shared> (a_Seed + 10, std::make_shared> (a_Seed + 100, 65 - ))))))))))))))))))))))))); + ))))))))))))))))))))))))))))); m_Gen = std::make_shared>(a_Seed, std::make_shared>(a_Seed, - std::make_shared>(a_Seed, - std::make_shared>(a_Seed, - std::make_shared> ( + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, + std::make_shared> ( FinalBiomes, FinalRivers - ))))); + )))))); } virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override @@ -1000,6 +1006,94 @@ protected: +//////////////////////////////////////////////////////////////////////////////// +// cBioGenGrown: + +class cBioGenProtGrown: + public cBiomeGen +{ +public: + cBioGenProtGrown(int a_Seed) + { + auto FinalRivers = + std::make_shared(a_Seed + 1, + std::make_shared(a_Seed + 3, + std::make_shared(a_Seed + 2, + std::make_shared(a_Seed + 4, + std::make_shared(a_Seed + 5, + std::make_shared(a_Seed + 6, + std::make_shared(a_Seed + 7, + std::make_shared(a_Seed + 8, + std::make_shared(a_Seed + 9, + std::make_shared(a_Seed + 10, + std::make_shared(a_Seed + 11, + std::make_shared(a_Seed + 12, 2 + )))))))))))); + + auto FinalBiomes = + std::make_shared(a_Seed + 1008, + std::make_shared(a_Seed + 15, + std::make_shared(a_Seed + 1000, + std::make_shared(a_Seed + 16, + std::make_shared( + std::make_shared(a_Seed + 1002, + std::make_shared(a_Seed + 1, + std::make_shared(a_Seed + 1002, + std::make_shared(a_Seed + 2, + std::make_shared(a_Seed + 2004, 10, + std::make_shared(a_Seed + 4, + std::make_shared(a_Seed + 9, 10, biMushroomIsland, + std::make_shared(biIcePlains, biIcePlainsSpikes, 5, a_Seed + 99, + std::make_shared(a_Seed + 8, + std::make_shared(a_Seed + 10, 500, biDeepOcean, + std::make_shared(a_Seed + 3000, + std::make_shared(a_Seed + 5, + std::make_shared( + std::make_shared(a_Seed + 1003, + std::make_shared(a_Seed + 7, + std::make_shared(a_Seed + 8, 50, bgOcean, + std::make_shared(bgJungle, bgTemperate, 50, a_Seed + 100, + std::make_shared(bgIce, bgTemperate, 50, a_Seed + 101, + std::make_shared(bgDesert, bgMesa, 30, a_Seed + 102, + std::make_shared(a_Seed + 2000, 70, + std::make_shared(a_Seed + 9, 50, bgOcean, + std::make_shared(a_Seed + 1004, + std::make_shared(a_Seed + 10, + std::make_shared(a_Seed + 100, 65 + ))))))))))))))))))))))))))))); + + m_Gen = + std::make_shared(a_Seed, + std::make_shared(a_Seed, + std::make_shared(a_Seed, + std::make_shared(a_Seed, + std::make_shared(a_Seed, + std::make_shared( + FinalBiomes, FinalRivers + )))))); + } + + virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override + { + int vals[16 * 16]; + m_Gen->GetInts(a_ChunkX * cChunkDef::Width, a_ChunkZ * cChunkDef::Width, 16, 16, vals); + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + cChunkDef::SetBiome(a_Biomes, x, z, (EMCSBiome)vals[x + cChunkDef::Width * z]); + } + } + } + +protected: + std::shared_ptr m_Gen; +}; + + + + + //////////////////////////////////////////////////////////////////////////////// // cBiomeGen: @@ -1040,6 +1134,10 @@ cBiomeGenPtr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & { res = new cBioGenGrown(a_Seed); } + else if (NoCaseCompare(BiomeGenName, "grownprot") == 0) + { + res = new cBioGenProtGrown(a_Seed); + } else { if (NoCaseCompare(BiomeGenName, "multistepmap") != 0) diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index afe30533e..1a26bd0d5 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -54,6 +54,7 @@ SET (HDRS PieceGenerator.h Prefab.h PrefabPiecePool.h + ProtIntGen.h RainbowRoadsGen.h Ravines.h RoughRavines.h diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index d7ed9275a..5f0394060 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -36,13 +36,14 @@ by using templates. /** Constants representing the biome group designators. */ -const int bgOcean = 0; -const int bgDesert = 1; -const int bgTemperate = 2; -const int bgMountains = 3; -const int bgJungle = 4; -const int bgIce = 5; -const int bgMax = 5; // Maximum biome group value +const int bgOcean = 0; +const int bgDesert = 1; +const int bgTemperate = 2; +const int bgMountains = 3; +const int bgJungle = 4; +const int bgIce = 5; +const int bgLandOceanMax = 5; // Maximum biome group value generated in the landOcean generator +const int bgMesa = 6; @@ -167,7 +168,7 @@ public: for (int x = 0; x < SizeX; x++) { int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); - a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgMax + 1) : 0; + a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; } } @@ -462,7 +463,7 @@ public: int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; if (rnd % 100 < m_Threshold) { - a_Values[x + z * SizeX] = (rnd / 100) % bgMax; + a_Values[x + z * SizeX] = (rnd / 100) % bgLandOceanMax; } } } @@ -521,16 +522,16 @@ public: case bgDesert: { if ( - !IsDesertCompatible(Above) || - !IsDesertCompatible(Below) || - !IsDesertCompatible(Left) || - !IsDesertCompatible(Right) + !isDesertCompatible(Above) || + !isDesertCompatible(Below) || + !isDesertCompatible(Left) || + !isDesertCompatible(Right) ) { v = bgTemperate; } break; - } + } // case bgDesert // Ice should not neighbor deserts; change to temperate: case bgIce: @@ -545,21 +546,36 @@ public: v = bgTemperate; } break; - } + } // case bgIce // Jungle should not neighbor Desert or Ice; change to temperate: case bgJungle: { if ( - !IsJungleCompatible(Above) || - !IsJungleCompatible(Below) || - !IsJungleCompatible(Left) || - !IsJungleCompatible(Right) + !isJungleCompatible(Above) || + !isJungleCompatible(Below) || + !isJungleCompatible(Left) || + !isJungleCompatible(Right) ) { v = bgTemperate; } - } + } // case bgJungle + + // Mesa should neighbor only oceans and deserts; change to desert when another: + case bgMesa: + { + if ( + !isMesaCompatible(Above) || + !isMesaCompatible(Below) || + !isMesaCompatible(Left) || + !isMesaCompatible(Right) + ) + { + v = bgDesert; + } + break; + } // case bgDesert } a_Values[x + z * SizeX] = v; } // for x @@ -570,14 +586,32 @@ protected: Underlying m_Underlying; - inline bool IsDesertCompatible(int a_BiomeGroup) + inline bool isDesertCompatible(int a_BiomeGroup) + { + switch (a_BiomeGroup) + { + case bgOcean: + case bgDesert: + case bgTemperate: + case bgMesa: + { + return true; + } + default: + { + return false; + } + } + } + + inline bool isJungleCompatible(int a_BiomeGroup) { - return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert) || (a_BiomeGroup == bgTemperate)); + return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce)); } - inline bool IsJungleCompatible(int a_BiomeGroup) + inline bool isMesaCompatible(int a_BiomeGroup) { - return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgIce)); + return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert)); } }; @@ -605,44 +639,50 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Define the per-biome-group biomes: - static const int OceanBiomes[] = + static const int oceanBiomes[] = { biOcean, // biDeepOcean, }; - static const int DesertBiomes[] = + static const int desertBiomes[] = { - biDesert, biDesert, biSavanna, biPlains, + biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; - static const int TemperateBiomes[] = + static const int temperateBiomes[] = { - biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, + biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; - static const int MountainBiomes[] = + static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; - static const int JungleBiomes[] = + static const int jungleBiomes[] = + { + biJungle, biJungle, biJungle, biForest, + }; + + static const int iceBiomes[] = { - biJungle, biJungle, biForest, + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const int IceBiomes[] = + static const int mesaBiomes[] = { - biIcePlains, biIcePlains, biColdTaiga, + biMesa, biMesaPlateau, }; static const cBiomesInGroups BiomesInGroups[] = { - { static_cast(ARRAYCOUNT(OceanBiomes)), OceanBiomes}, - { static_cast(ARRAYCOUNT(DesertBiomes)), DesertBiomes}, - { static_cast(ARRAYCOUNT(TemperateBiomes)), TemperateBiomes}, - { static_cast(ARRAYCOUNT(MountainBiomes)), MountainBiomes}, - { static_cast(ARRAYCOUNT(JungleBiomes)), JungleBiomes}, - { static_cast(ARRAYCOUNT(IceBiomes)), IceBiomes}, + /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, + /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, + /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, }; // Generate the underlying values, representing biome groups: @@ -951,3 +991,56 @@ protected: + +/** Changes random pixels of the underlying data to the specified value. */ +template +class cIntGenSetRandomly : + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + cIntGenSetRandomly(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying) : + super(a_Seed), + m_Chance(a_Chance), + m_ToValue(a_ToValue), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + + // Change random pixels to bgOcean: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + a_Values[x + z * SizeX] = m_ToValue; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel. */ + int m_Chance; + + /** The value to which to set the pixel. */ + int m_ToValue; + + Underlying m_Underlying; +}; + + + + + diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h new file mode 100644 index 000000000..a3d10c4ef --- /dev/null +++ b/src/Generating/ProtIntGen.h @@ -0,0 +1,1008 @@ + +// ProtIntGen.h + +// Declares the prototyping integer generators - cProtIntGen class and its descendants + +/* +These classes generate 2D arrays of integers that have various interpretations. The main purpose of these +classes is to provide fast prototyping for cIntGen classes - unlike cIntGen classes, these are not +template-based and so they take care of the underlying sizes automatically. This makes them easier to chain +and re-chain, since the size parameters don't need to be adjusted after each such case. Their performance is, +however, slightly worse, which is why we use cIntGen classes in the final generator. + +Because there is no SizeX / SizeZ template param, the generators would have to either alloc memory for each +underlying generator's values, or use a maximum-size buffer. We chose the latter, to avoid memory allocation +overhead; this however means that there's (an arbitrary) limit to the size of the generated data. +*/ + + + + + +#pragma once + +// We need the biome group constants defined there: +#include "IntGen.h" + + + + + +/** Interface that all the generator classes provide. */ +class cProtIntGen +{ +protected: + /** Maximum size of the generated area. + Adjust the constant if you need larger areas, these are just so that we can use fixed-size buffers. */ + static const int m_BufferSize = 900; + +public: + + /** Type of the generic interface used for storing links to the underlying generators. */ + typedef std::shared_ptr Underlying; + + + /** Force a virtual destructor in all descendants. + Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */ + virtual ~cProtIntGen() {} + + /** Generates the array of specified size into a_Values, based on given min coords. */ + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) = 0; +}; + + + + + +/** Provides additional cNoise member and its helper functions. */ +class cProtIntGenWithNoise : + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenWithNoise(int a_Seed) : + m_Noise(a_Seed) + { + } + +protected: + cNoise m_Noise; + + /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ + int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) + { + int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; + return ((rnd & 1) == 0) ? a_Val1 : a_Val2; + } + + /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ + int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) + { + int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; + switch (rnd % 4) + { + case 0: return a_Val1; + case 1: return a_Val2; + case 2: return a_Val3; + default: return a_Val4; + } + } +}; + + + + + + +/** Generates a 2D array of random integers in the specified range [0 .. Range). */ +class cProtIntGenChoice : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenChoice(int a_Seed, int a_Range) : + super(a_Seed), + m_Range(a_Range) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + for (int z = 0; z < a_SizeZ; z++) + { + int BaseZ = a_MinZ + z; + for (int x = 0; x < a_SizeX; x++) + { + a_Values[x + a_SizeX * z] = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % m_Range; + } + } // for z + } + +protected: + int m_Range; +}; + + + + + + +/** Decides between the ocean and landmass biomes. +Has a threshold (in percent) of how much land, the larger the threshold, the more land. +Generates 0 for ocean, biome group ID for landmass. */ +class cProtIntGenLandOcean : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenLandOcean(int a_Seed, int a_Threshold) : + super(a_Seed), + m_Threshold(a_Threshold) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + for (int z = 0; z < a_SizeZ; z++) + { + int BaseZ = a_MinZ + z; + for (int x = 0; x < a_SizeX; x++) + { + int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); + a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; + } + } + + // If the centerpoint of the world is within the area, set it to bgTemperate, always: + if ((a_MinX <= 0) && (a_MinZ <= 0) && (a_MinX + a_SizeX > 0) && (a_MinZ + a_SizeZ > 0)) + { + a_Values[-a_MinX - a_MinZ * a_SizeX] = bgTemperate; + } + } + +protected: + int m_Threshold; +}; + + + + + +class cProtIntGenZoom : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenZoom(int a_Seed, Underlying a_UnderlyingGen) : + super(a_Seed), + m_UnderlyingGen(a_UnderlyingGen) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Get the coords for the lower generator: + int lowerMinX = a_MinX >> 1; + int lowerMinZ = a_MinZ >> 1; + int lowerSizeX = a_SizeX / 2 + 2; + int lowerSizeZ = a_SizeZ / 2 + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + ASSERT(lowerSizeX > 0); + ASSERT(lowerSizeZ > 0); + + // Generate the underlying data with half the resolution: + int lowerData[m_BufferSize]; + m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerSizeX, lowerSizeZ, lowerData); + const int lowStepX = (lowerSizeX - 1) * 2; + int Cache[m_BufferSize]; + + // Discreet-interpolate the values into twice the size: + for (int z = 0; z < lowerSizeZ - 1; ++z) + { + int idx = (z * 2) * lowStepX; + int PrevZ0 = lowerData[z * lowerSizeX]; + int PrevZ1 = lowerData[(z + 1) * lowerSizeX]; + + for (int x = 0; x < lowerSizeX - 1; ++x) + { + int ValX1Z0 = lowerData[x + 1 + z * lowerSizeX]; + int ValX1Z1 = lowerData[x + 1 + (z + 1) * lowerSizeX]; + int RndX = (x + lowerMinX) * 2; + int RndZ = (z + lowerMinZ) * 2; + Cache[idx] = PrevZ0; + Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); + idx++; + Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); + Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx++; + PrevZ0 = ValX1Z0; + PrevZ1 = ValX1Z1; + } + } + + // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: + for (int z = 0; z < a_SizeZ; ++z) + { + memcpy(a_Values + z * a_SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); + } + } + +protected: + Underlying m_UnderlyingGen; +}; + + + + + +class cProtIntGenSmooth : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenSmooth(int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying values: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerData[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData); + + // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. + // Also get rid of single-pixel irregularities (A-B-A): + for (int z = 0; z < a_SizeZ; z++) + { + int NoiseZ = a_MinZ + z; + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerData[x + 1 + (z + 1) * lowerSizeX]; + int Above = lowerData[x + 1 + z * lowerSizeX]; + int Below = lowerData[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerData[x + (z + 1) * lowerSizeX]; + int Right = lowerData[x + 2 + (z + 1) * lowerSizeX]; + + if ((Left == Right) && (Above == Below)) + { + if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) + { + val = Left; + } + else + { + val = Above; + } + } + else + { + if (Left == Right) + { + val = Left; + } + + if (Above == Below) + { + val = Above; + } + } + + a_Values[x + z * a_SizeX] = val; + } + } + } + +protected: + Underlying m_Underlying; +}; + + + + + +class cProtIntGenBeaches : + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenBeaches(Underlying a_Underlying) : + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Map for biome -> its beach: + static const int ToBeach[] = + { + /* biOcean */ biOcean, + /* biPlains */ biBeach, + /* biDesert */ biBeach, + /* biExtremeHills */ biStoneBeach, + /* biForest */ biBeach, + /* biTaiga */ biColdBeach, + /* biSwampland */ biSwampland, + /* biRiver */ biRiver, + /* biNether */ biNether, + /* biEnd */ biEnd, + /* biFrozenOcean */ biColdBeach, + /* biFrozenRiver */ biColdBeach, + /* biIcePlains */ biColdBeach, + /* biIceMountains */ biColdBeach, + /* biMushroomIsland */ biMushroomShore, + /* biMushroomShore */ biMushroomShore, + /* biBeach */ biBeach, + /* biDesertHills */ biBeach, + /* biForestHills */ biBeach, + /* biTaigaHills */ biColdBeach, + /* biExtremeHillsEdge */ biStoneBeach, + /* biJungle */ biBeach, + /* biJungleHills */ biBeach, + /* biJungleEdge */ biBeach, + /* biDeepOcean */ biOcean, + /* biStoneBeach */ biStoneBeach, + /* biColdBeach */ biColdBeach, + /* biBirchForest */ biBeach, + /* biBirchForestHills */ biBeach, + /* biRoofedForest */ biBeach, + /* biColdTaiga */ biColdBeach, + /* biColdTaigaHills */ biColdBeach, + /* biMegaTaiga */ biStoneBeach, + /* biMegaTaigaHills */ biStoneBeach, + /* biExtremeHillsPlus */ biStoneBeach, + /* biSavanna */ biBeach, + /* biSavannaPlateau */ biBeach, + /* biMesa */ biMesa, + /* biMesaPlateauF */ biMesa, + /* biMesaPlateau */ biMesa, + }; + + // Generate the underlying values: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Add beaches between ocean and biomes: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + if (!IsBiomeOcean(val)) + { + if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + { + val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; + } + } + a_Values[x + z * a_SizeX] = val; + } + } + } + +protected: + Underlying m_Underlying; +}; + + + + + +/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +class cProtIntGenAddIslands : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + typedef std::shared_ptr Underlying; + + + cProtIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + super(a_Seed), + m_Threshold(a_Threshold), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + if (a_Values[x + z * a_SizeX] == bgOcean) + { + int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; + if (rnd % 100 < m_Threshold) + { + a_Values[x + z * a_SizeX] = (rnd / 100) % bgLandOceanMax; + } + } + } + } + } + +protected: + int m_Threshold; + + Underlying m_Underlying; +}; + + + + + +/** A filter that adds an edge biome group between two biome groups that need an edge between them. */ +class cProtIntGenBiomeGroupEdges : + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenBiomeGroupEdges(Underlying a_Underlying) : + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) + { + // Generate the underlying biome groups: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerValues); + + // Change the biomes on incompatible edges into an edge biome: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + switch (val) + { + // Desert should neighbor only oceans, desert and temperates; change to temperate when another: + case bgDesert: + { + if ( + !isDesertCompatible(Above) || + !isDesertCompatible(Below) || + !isDesertCompatible(Left) || + !isDesertCompatible(Right) + ) + { + val = bgTemperate; + } + break; + } // case bgDesert + + // Ice should not neighbor deserts; change to temperate: + case bgIce: + { + if ( + (Above == bgDesert) || + (Below == bgDesert) || + (Left == bgDesert) || + (Right == bgDesert) + ) + { + val = bgTemperate; + } + break; + } // case bgIce + + // Jungle should not neighbor Desert or Ice; change to temperate: + case bgJungle: + { + if ( + !isJungleCompatible(Above) || + !isJungleCompatible(Below) || + !isJungleCompatible(Left) || + !isJungleCompatible(Right) + ) + { + val = bgTemperate; + } + } // case bgJungle + + // Mesa should neighbor only oceans and deserts; change to desert when another: + case bgMesa: + { + if ( + !isMesaCompatible(Above) || + !isMesaCompatible(Below) || + !isMesaCompatible(Left) || + !isMesaCompatible(Right) + ) + { + val = bgDesert; + } + break; + } // case bgDesert + } + a_Values[x + z * a_SizeX] = val; + } // for x + } // for z + } + +protected: + Underlying m_Underlying; + + + inline bool isDesertCompatible(int a_BiomeGroup) + { + switch (a_BiomeGroup) + { + case bgOcean: + case bgDesert: + case bgTemperate: + case bgMesa: + { + return true; + } + default: + { + return false; + } + } + } + + inline bool isJungleCompatible(int a_BiomeGroup) + { + return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce)); + } + + inline bool isMesaCompatible(int a_BiomeGroup) + { + return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert)); + } +}; + + + + + +/** Turns biome group indices into real biomes. +For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with +that biome. */ +class cProtIntGenBiomes : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenBiomes(int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Define the per-biome-group biomes: + static const int oceanBiomes[] = + { + biOcean, // biDeepOcean, + }; + + static const int desertBiomes[] = + { + biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, + }; + + static const int temperateBiomes[] = + { + biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, + }; + + static const int mountainBiomes[] = + { + biExtremeHills, biForest, biTaiga, biPlains, + }; + + static const int jungleBiomes[] = + { + biJungle, biJungle, biJungle, biForest, + }; + + static const int iceBiomes[] = + { + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, + }; + + static const int mesaBiomes[] = + { + biMesa, biMesaPlateau, + }; + + static const cBiomesInGroups BiomesInGroups[] = + { + /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, + /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, + /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, + }; + + // Generate the underlying values, representing biome groups: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Overwrite each biome group with a random biome from that group: + for (int z = 0; z < a_SizeZ; z++) + { + int IdxZ = z * a_SizeX; + for (int x = 0; x < a_SizeX; x++) + { + int val = a_Values[x + IdxZ]; + const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); + a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; + } + } + } + +protected: + + struct cBiomesInGroups + { + const int Count; + const int * Biomes; + }; + + + /** The underlying int generator */ + Underlying m_Underlying; +}; + + + + + +class cProtIntGenReplaceRandomly : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + typedef std::shared_ptr Underlying; + + + cProtIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) : + super(a_Seed), + m_From(a_From), + m_To(a_To), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying values: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Replace some of the values: + for (int z = 0; z < a_SizeZ; z++) + { + int idxZ = z * a_SizeX; + for (int x = 0; x < a_SizeX; x++) + { + int idx = x + idxZ; + if (a_Values[idx] == m_From) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 100 < m_Chance) + { + a_Values[idx] = m_To; + } + } + } + } // for z + } + + +protected: + int m_From; + int m_To; + int m_Chance; + Underlying m_Underlying; +}; + + + + + +/** Mixer that joins together finalized biomes and rivers. +It first checks for oceans; if there's no ocean, it checks for a river. */ +class cProtIntGenMixRivers: + public cProtIntGen +{ + typedef cProtIntGen super; + +public: + cProtIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers): + m_Biomes(a_Biomes), + m_Rivers(a_Rivers) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + ASSERT(a_SizeX * a_SizeZ <= m_BufferSize); + m_Biomes->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + int riverData[m_BufferSize]; + m_Rivers->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, riverData); + + // Mix the values: + for (int z = 0; z < a_SizeZ; z++) + { + int idxZ = z * a_SizeX; + for (int x = 0; x < a_SizeX; x++) + { + int idx = x + idxZ; + if (IsBiomeOcean(a_Values[idx])) + { + // Oceans are kept without any changes + continue; + } + if (riverData[idx] != biRiver) + { + // There's no river, keep the current value + continue; + } + + // There's a river, change the output to a river or a frozen river, based on the original biome: + if (IsBiomeVeryCold((EMCSBiome)a_Values[idx])) + { + a_Values[idx] = biFrozenRiver; + } + else + { + a_Values[idx] = biRiver; + } + } // for x + } // for z + } + +protected: + Underlying m_Biomes; + Underlying m_Rivers; +}; + + + + + +/** Generates a river based on the underlying data. +This is basically an edge detector over the underlying data. The rivers are the edges where the underlying +data changes from one pixel to its neighbor. */ +class cProtIntGenRiver: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenRiver(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Detect the edges: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + + if ((val == Above) && (val == Below) && (val == Left) && (val == Right)) + { + val = 0; + } + else + { + val = biRiver; + } + a_Values[x + z * a_SizeX] = val; + } // for x + } // for z + } + +protected: + Underlying m_Underlying; +}; + + + + + +/** Turns some of the oceans into the specified biome. Used for mushroom and deep ocean. +The biome is only placed if at least 3 of its neighbors are ocean and only with the specified chance. */ +class cProtIntGenAddToOcean: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_ToValue(a_ToValue), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Add the mushroom islands: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + if (!IsBiomeOcean(val)) + { + a_Values[x + z * a_SizeX] = val; + continue; + } + + // Count the ocean neighbors: + int Above = lowerValues[x + 1 + z * lowerSizeX]; + int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int Left = lowerValues[x + (z + 1) * lowerSizeX]; + int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + int NumOceanNeighbors = 0; + if (IsBiomeOcean(Above)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Below)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Left)) + { + NumOceanNeighbors += 1; + } + if (IsBiomeOcean(Right)) + { + NumOceanNeighbors += 1; + } + + // If at least 3 ocean neighbors and the chance is right, change: + if ( + (NumOceanNeighbors >= 3) && + ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance) + ) + { + a_Values[x + z * a_SizeX] = m_ToValue; + } + else + { + a_Values[x + z * a_SizeX] = val; + } + } // for x + } // for z + } + +protected: + /** Chance, in permille, of changing the biome. */ + int m_Chance; + + /** The value to change the ocean into. */ + int m_ToValue; + + Underlying m_Underlying; +}; + + + + + +/** Changes random pixels of the underlying data to the specified value. */ +class cProtIntGenSetRandomly : + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenSetRandomly(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying) : + super(a_Seed), + m_Chance(a_Chance), + m_ToValue(a_ToValue), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Change random pixels to bgOcean: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + a_Values[x + z * a_SizeX] = m_ToValue; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel. */ + int m_Chance; + + /** The value to which to set the pixel. */ + int m_ToValue; + + Underlying m_Underlying; +}; + + + + + -- cgit v1.2.3 From 13f0e93d690ef5ca96689190356b5c6c9cceb434 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 31 Oct 2014 12:52:07 +0100 Subject: GrownProt biomes: added alterations. --- src/Generating/BioGen.cpp | 56 ++++++------ src/Generating/IntGen.h | 53 ++--------- src/Generating/ProtIntGen.h | 213 ++++++++++++++++++++++++++++++++------------ 3 files changed, 192 insertions(+), 130 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index f9a0a571b..b3701a32a 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -964,15 +964,13 @@ public: std::make_shared> (a_Seed + 1003, std::make_shared> (a_Seed + 7, std::make_shared> (a_Seed + 8, 50, bgOcean, - std::make_shared> (bgJungle, bgTemperate, 50, a_Seed + 100, std::make_shared> (bgIce, bgTemperate, 50, a_Seed + 101, - std::make_shared> (bgDesert, bgMesa, 30, a_Seed + 102, std::make_shared> (a_Seed + 2000, 70, std::make_shared> (a_Seed + 9, 50, bgOcean, std::make_shared> (a_Seed + 1004, std::make_shared> (a_Seed + 10, std::make_shared> (a_Seed + 100, 65 - ))))))))))))))))))))))))))))); + ))))))))))))))))))))))))))); m_Gen = std::make_shared>(a_Seed, @@ -1017,60 +1015,66 @@ public: { auto FinalRivers = std::make_shared(a_Seed + 1, - std::make_shared(a_Seed + 3, - std::make_shared(a_Seed + 2, - std::make_shared(a_Seed + 4, - std::make_shared(a_Seed + 5, - std::make_shared(a_Seed + 6, - std::make_shared(a_Seed + 7, + std::make_shared(a_Seed + 2, + std::make_shared(a_Seed + 3, + std::make_shared(a_Seed + 4, + std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 8, + std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 9, + std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 10, + std::make_shared(a_Seed + 5, + std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 11, std::make_shared(a_Seed + 12, 2 - )))))))))))); + )))))))))))))); + + auto alteration = + std::make_shared(a_Seed, + std::make_shared(a_Seed, 20 + )); auto FinalBiomes = - std::make_shared(a_Seed + 1008, + std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 15, - std::make_shared(a_Seed + 1000, + std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 16, std::make_shared( - std::make_shared(a_Seed + 1002, std::make_shared(a_Seed + 1, - std::make_shared(a_Seed + 1002, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 2004, 10, + std::make_shared(a_Seed + 10, 500, biDeepOcean, + std::make_shared(a_Seed + 1, biPlains, biSunflowerPlains, 20, + std::make_shared(a_Seed + 1, alteration, std::make_shared(a_Seed + 4, - std::make_shared(a_Seed + 9, 10, biMushroomIsland, - std::make_shared(biIcePlains, biIcePlainsSpikes, 5, a_Seed + 99, + std::make_shared(a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50, std::make_shared(a_Seed + 8, - std::make_shared(a_Seed + 10, 500, biDeepOcean, + std::make_shared(a_Seed + 10, 300, biDeepOcean, + std::make_shared(a_Seed + 9, 8, biMushroomIsland, std::make_shared(a_Seed + 3000, + std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 5, + std::make_shared(a_Seed + 5, 50, std::make_shared( - std::make_shared(a_Seed + 1003, + std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 7, std::make_shared(a_Seed + 8, 50, bgOcean, - std::make_shared(bgJungle, bgTemperate, 50, a_Seed + 100, - std::make_shared(bgIce, bgTemperate, 50, a_Seed + 101, - std::make_shared(bgDesert, bgMesa, 30, a_Seed + 102, - std::make_shared(a_Seed + 2000, 70, + std::make_shared(a_Seed + 101, bgIce, bgTemperate, 150, + std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 9, 50, bgOcean, - std::make_shared(a_Seed + 1004, std::make_shared(a_Seed + 10, - std::make_shared(a_Seed + 100, 65 + std::make_shared(a_Seed + 100, 30 ))))))))))))))))))))))))))))); m_Gen = std::make_shared(a_Seed, std::make_shared(a_Seed, - std::make_shared(a_Seed, std::make_shared(a_Seed, std::make_shared(a_Seed, std::make_shared( FinalBiomes, FinalRivers - )))))); + ))))); } virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 5f0394060..15a5c9157 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -8,13 +8,13 @@ The integers generated may be interpreted in several ways: - land/see designators - 0 = ocean - >0 = land -- biome group designators +- biome group - 0 = ocean - 1 = desert biomes - 2 = temperate biomes - 3 = mountains (hills and forests) - - 4 = jungle - - 5 = ice biomes + - 4 = ice biomes +- biome group with "bgfRare" flag (for generating rare biomes for the group) - biome IDs The interpretation depends on the generator used and on the position in the chain. @@ -40,10 +40,9 @@ const int bgOcean = 0; const int bgDesert = 1; const int bgTemperate = 2; const int bgMountains = 3; -const int bgJungle = 4; -const int bgIce = 5; -const int bgLandOceanMax = 5; // Maximum biome group value generated in the landOcean generator -const int bgMesa = 6; +const int bgIce = 4; +const int bgLandOceanMax = 4; // Maximum biome group value generated in the landOcean generator +const int bgfRare = 1024; // Flag added to values to generate rare biomes for the group @@ -547,35 +546,6 @@ public: } break; } // case bgIce - - // Jungle should not neighbor Desert or Ice; change to temperate: - case bgJungle: - { - if ( - !isJungleCompatible(Above) || - !isJungleCompatible(Below) || - !isJungleCompatible(Left) || - !isJungleCompatible(Right) - ) - { - v = bgTemperate; - } - } // case bgJungle - - // Mesa should neighbor only oceans and deserts; change to desert when another: - case bgMesa: - { - if ( - !isMesaCompatible(Above) || - !isMesaCompatible(Below) || - !isMesaCompatible(Left) || - !isMesaCompatible(Right) - ) - { - v = bgDesert; - } - break; - } // case bgDesert } a_Values[x + z * SizeX] = v; } // for x @@ -593,7 +563,6 @@ protected: case bgOcean: case bgDesert: case bgTemperate: - case bgMesa: { return true; } @@ -603,16 +572,6 @@ protected: } } } - - inline bool isJungleCompatible(int a_BiomeGroup) - { - return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce)); - } - - inline bool isMesaCompatible(int a_BiomeGroup) - { - return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert)); - } }; diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index a3d10c4ef..e2b3e592a 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -154,7 +154,7 @@ public: for (int x = 0; x < a_SizeX; x++) { int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); - a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; + a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0; } } @@ -410,7 +410,8 @@ protected: -/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +/** Generates the underlying numbers and then randomly changes some ocean group pixels into random land +group pixels, based on the predefined chance. */ class cProtIntGenAddIslands : public cProtIntGenWithNoise { @@ -420,9 +421,9 @@ public: typedef std::shared_ptr Underlying; - cProtIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + cProtIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying) : super(a_Seed), - m_Threshold(a_Threshold), + m_Chance(a_Chance), m_Underlying(a_Underlying) { } @@ -438,9 +439,9 @@ public: if (a_Values[x + z * a_SizeX] == bgOcean) { int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; - if (rnd % 100 < m_Threshold) + if (rnd % 1000 < m_Chance) { - a_Values[x + z * a_SizeX] = (rnd / 100) % bgLandOceanMax; + a_Values[x + z * a_SizeX] = (rnd / 101) % bgLandOceanMax; } } } @@ -448,7 +449,8 @@ public: } protected: - int m_Threshold; + /** Chance of each ocean pixel being converted, in permille. */ + int m_Chance; Underlying m_Underlying; }; @@ -520,35 +522,6 @@ public: } break; } // case bgIce - - // Jungle should not neighbor Desert or Ice; change to temperate: - case bgJungle: - { - if ( - !isJungleCompatible(Above) || - !isJungleCompatible(Below) || - !isJungleCompatible(Left) || - !isJungleCompatible(Right) - ) - { - val = bgTemperate; - } - } // case bgJungle - - // Mesa should neighbor only oceans and deserts; change to desert when another: - case bgMesa: - { - if ( - !isMesaCompatible(Above) || - !isMesaCompatible(Below) || - !isMesaCompatible(Left) || - !isMesaCompatible(Right) - ) - { - val = bgDesert; - } - break; - } // case bgDesert } a_Values[x + z * a_SizeX] = val; } // for x @@ -566,7 +539,6 @@ protected: case bgOcean: case bgDesert: case bgTemperate: - case bgMesa: { return true; } @@ -576,16 +548,6 @@ protected: } } } - - inline bool isJungleCompatible(int a_BiomeGroup) - { - return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce)); - } - - inline bool isMesaCompatible(int a_BiomeGroup) - { - return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert)); - } }; @@ -616,24 +578,40 @@ public: biOcean, // biDeepOcean, }; + // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) + static const int rareOceanBiomes[] = + { + biOcean, + }; + static const int desertBiomes[] = { biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; + static const int rareDesertBiomes[] = + { + biMesaPlateau, biMesaPlateauF, + }; + static const int temperateBiomes[] = { biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; + static const int rareTemperateBiomes[] = + { + biJungle, // Jungle is not strictly temperate, but let's piggyback it here + }; + static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; - static const int jungleBiomes[] = + static const int rareMountainBiomes[] = { - biJungle, biJungle, biJungle, biForest, + biMegaTaiga, }; static const int iceBiomes[] = @@ -641,33 +619,44 @@ public: biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const int mesaBiomes[] = + // Same as iceBiomes, there's no rare ice biome + static const int rareIceBiomes[] = { - biMesa, biMesaPlateau, + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const cBiomesInGroups BiomesInGroups[] = + static const cBiomesInGroups biomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, - /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, - /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, + }; + + static const cBiomesInGroups rareBiomesInGroups[] = + { + /* bgOcean */ { static_cast(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes}, }; // Generate the underlying values, representing biome groups: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Overwrite each biome group with a random biome from that group: + // Take care of the bgfRare flag for (int z = 0; z < a_SizeZ; z++) { int IdxZ = z * a_SizeX; for (int x = 0; x < a_SizeX; x++) { int val = a_Values[x + IdxZ]; - const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + const cBiomesInGroups & Biomes = (val > bgfRare) ? + rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] : + biomesInGroups[val % ARRAYCOUNT(biomesInGroups)]; int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } @@ -700,7 +689,7 @@ public: typedef std::shared_ptr Underlying; - cProtIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) : + cProtIntGenReplaceRandomly(int a_Seed, int a_From, int a_To, int a_Chance, Underlying a_Underlying) : super(a_Seed), m_From(a_From), m_To(a_To), @@ -725,7 +714,7 @@ public: if (a_Values[idx] == m_From) { int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; - if (rnd % 100 < m_Chance) + if (rnd % 1000 < m_Chance) { a_Values[idx] = m_To; } @@ -1006,3 +995,113 @@ protected: + +/** Adds a "rare" flag to random biome groups, based on the given chance. */ +class cProtIntGenRareBiomeGroups: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + + // Change some of the biome groups into rare biome groups: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + int idx = x + a_SizeX * z; + a_Values[idx] = a_Values[idx] | bgfRare; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel into the rare biome group. */ + int m_Chance; + + /** The underlying generator. */ + Underlying m_Underlying; +}; + + + + + +/** Changes biomes in the parent data into their alternate verions ("M" variants), in such places that +have their alterations set. */ +class cProtIntGenAlternateBiomes: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes): + super(a_Seed), + m_Alterations(a_Alterations), + m_BaseBiomes(a_BaseBiomes) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the base biomes and the alterations: + m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + int alterations[m_BufferSize]; + m_Alterations->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, alterations); + + // Change the biomes into their alternate versions: + int len = a_SizeX * a_SizeZ; + for (int idx = 0; idx < len; ++idx) + { + if (alterations[idx] == 0) + { + // No change + continue; + } + + // Change to alternate biomes: + int val = a_Values[idx]; + switch (val) + { + case biBirchForest: val = biBirchForest; break; + case biDesert: val = biDesertHills; break; + case biExtremeHills: val = biExtremeHillsPlus; break; + case biForest: val = biForestHills; break; + case biIcePlains: val = biIceMountains; break; + case biJungle: val = biJungleHills; break; + case biMegaTaiga: val = biMegaTaigaHills; break; + case biMesaPlateau: val = biMesa; break; + case biPlains: val = biForest; break; + case biRoofedForest: val = biPlains; break; + case biSavanna: val = biSavannaPlateau; break; + case biTaiga: val = biTaigaHills; break; + } + a_Values[idx] = val; + } // for idx - a_Values[] + } + +protected: + Underlying m_Alterations; + Underlying m_BaseBiomes; +}; + + + + -- cgit v1.2.3 From 4873890cfbb0c1a2ede464c44ffb58bfe4a1c1cd Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 1 Nov 2014 16:37:56 +0100 Subject: GrownProt biome gen: Added biome edges. --- src/Generating/BioGen.cpp | 5 +- src/Generating/ProtIntGen.h | 159 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index b3701a32a..e4a3a3629 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -1042,11 +1042,12 @@ public: std::make_shared(a_Seed + 16, std::make_shared( std::make_shared(a_Seed + 1, - std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 2004, 10, std::make_shared(a_Seed + 10, 500, biDeepOcean, std::make_shared(a_Seed + 1, biPlains, biSunflowerPlains, 20, std::make_shared(a_Seed + 1, alteration, + std::make_shared(a_Seed + 3, + std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 4, std::make_shared(a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50, std::make_shared(a_Seed + 8, @@ -1065,7 +1066,7 @@ public: std::make_shared(a_Seed + 9, 50, bgOcean, std::make_shared(a_Seed + 10, std::make_shared(a_Seed + 100, 30 - ))))))))))))))))))))))))))))); + )))))))))))))))))))))))))))))); m_Gen = std::make_shared(a_Seed, diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index e2b3e592a..c523d9d52 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -1088,6 +1088,7 @@ public: case biJungle: val = biJungleHills; break; case biMegaTaiga: val = biMegaTaigaHills; break; case biMesaPlateau: val = biMesa; break; + case biMesaPlateauF: val = biMesa; break; case biPlains: val = biForest; break; case biRoofedForest: val = biPlains; break; case biSavanna: val = biSavannaPlateau; break; @@ -1105,3 +1106,161 @@ protected: + +/** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */ +class cProtIntGenBiomeEdges: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenBiomeEdges(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying biomes: + int lowerSizeX = a_SizeX + 2; + int lowerSizeZ = a_SizeZ + 2; + ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); + int lowerValues[m_BufferSize]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); + + // Convert incompatible edges into neutral biomes: + for (int z = 0; z < a_SizeZ; z++) + { + for (int x = 0; x < a_SizeX; x++) + { + int biome = lowerValues[x + 1 + (z + 1) * lowerSizeX]; + int above = lowerValues[x + 1 + z * lowerSizeX]; + int below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int left = lowerValues[x + (z + 1) * lowerSizeX]; + int right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + + switch (biome) + { + case biDesert: + case biDesertM: + case biDesertHills: + { + if ( + IsBiomeVeryCold(static_cast(above)) || + IsBiomeVeryCold(static_cast(below)) || + IsBiomeVeryCold(static_cast(left)) || + IsBiomeVeryCold(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // case biDesert + + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + { + if ( + !isMesaCompatible(above) || + !isMesaCompatible(below) || + !isMesaCompatible(left) || + !isMesaCompatible(right) + ) + { + biome = biDesert; + } + break; + } // Mesa biomes + + case biJungle: + case biJungleM: + { + if ( + !isJungleCompatible(above) || + !isJungleCompatible(below) || + !isJungleCompatible(left) || + !isJungleCompatible(right) + ) + { + biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM; + } + break; + } // Jungle biomes + + case biSwampland: + case biSwamplandM: + { + if ( + IsBiomeNoDownfall(static_cast(above)) || + IsBiomeNoDownfall(static_cast(below)) || + IsBiomeNoDownfall(static_cast(left)) || + IsBiomeNoDownfall(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // Swampland biomes + } // switch (biome) + + a_Values[x + z * a_SizeX] = biome; + } // for x + } // for z + } + + +protected: + Underlying m_Underlying; + + + bool isMesaCompatible(int a_Biome) + { + switch (a_Biome) + { + case biDesert: + case biMesa: + case biMesaBryce: + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + case biOcean: + case biDeepOcean: + { + return true; + } + default: + { + return false; + } + } + } + + + bool isJungleCompatible(int a_Biome) + { + switch (a_Biome) + { + case biJungle: + case biJungleM: + case biJungleEdge: + case biJungleEdgeM: + case biJungleHills: + { + return true; + } + default: + { + return false; + } + } + } +}; + + + + -- cgit v1.2.3 From d868346491cf35ea9d52d60786904b0552d9d67c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 1 Nov 2014 21:01:33 +0100 Subject: GrownProt: Added the rest of rare and M biomes. --- src/Generating/BioGen.cpp | 11 +++++- src/Generating/ProtIntGen.h | 94 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 91 insertions(+), 14 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index e4a3a3629..dc5f715ca 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -1035,6 +1035,14 @@ public: std::make_shared(a_Seed, 20 )); + auto alteration2 = + std::make_shared(a_Seed + 1, + std::make_shared(a_Seed + 2, + std::make_shared(a_Seed + 1, + std::make_shared(a_Seed + 2, + std::make_shared(a_Seed + 1, 10 + ))))); + auto FinalBiomes = std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 15, @@ -1045,6 +1053,7 @@ public: std::make_shared(a_Seed + 2004, 10, std::make_shared(a_Seed + 10, 500, biDeepOcean, std::make_shared(a_Seed + 1, biPlains, biSunflowerPlains, 20, + std::make_shared(a_Seed + 5, alteration2, std::make_shared(a_Seed + 1, alteration, std::make_shared(a_Seed + 3, std::make_shared(a_Seed + 2, @@ -1066,7 +1075,7 @@ public: std::make_shared(a_Seed + 9, 50, bgOcean, std::make_shared(a_Seed + 10, std::make_shared(a_Seed + 100, 30 - )))))))))))))))))))))))))))))); + ))))))))))))))))))))))))))))))); m_Gen = std::make_shared(a_Seed, diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index c523d9d52..9c3eb36cc 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -1080,19 +1080,21 @@ public: int val = a_Values[idx]; switch (val) { - case biBirchForest: val = biBirchForest; break; - case biDesert: val = biDesertHills; break; - case biExtremeHills: val = biExtremeHillsPlus; break; - case biForest: val = biForestHills; break; - case biIcePlains: val = biIceMountains; break; - case biJungle: val = biJungleHills; break; - case biMegaTaiga: val = biMegaTaigaHills; break; - case biMesaPlateau: val = biMesa; break; - case biMesaPlateauF: val = biMesa; break; - case biPlains: val = biForest; break; - case biRoofedForest: val = biPlains; break; - case biSavanna: val = biSavannaPlateau; break; - case biTaiga: val = biTaigaHills; break; + case biBirchForest: val = biBirchForest; break; + case biDesert: val = biDesertHills; break; + case biExtremeHills: val = biExtremeHillsPlus; break; + case biForest: val = biForestHills; break; + case biIcePlains: val = biIceMountains; break; + case biJungle: val = biJungleHills; break; + case biMegaTaiga: val = biMegaTaigaHills; break; + case biMesaPlateau: val = biMesa; break; + case biMesaPlateauF: val = biMesa; break; + case biMesaPlateauM: val = biMesa; break; + case biMesaPlateauFM: val = biMesa; break; + case biPlains: val = biForest; break; + case biRoofedForest: val = biPlains; break; + case biSavanna: val = biSavannaPlateau; break; + case biTaiga: val = biTaigaHills; break; } a_Values[idx] = val; } // for idx - a_Values[] @@ -1264,3 +1266,69 @@ protected: + +class cProtIntGenMBiomes: + public cProtIntGenWithNoise +{ + typedef cProtIntGenWithNoise super; + +public: + cProtIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying), + m_Alteration(a_Alteration) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, int a_SizeX, int a_SizeZ, int * a_Values) override + { + // Generate the underlying biomes and the alterations: + m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); + int alterations[m_BufferSize]; + m_Alteration->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, alterations); + + // Wherever alterations are nonzero, change into alternate biome, if available: + int len = a_SizeX * a_SizeZ; + for (int idx = 0; idx < len; ++idx) + { + if (alterations[idx] == 0) + { + continue; + } + + // Ice spikes biome was removed from here, because it was generated way too often + switch (a_Values[idx]) + { + case biPlains: a_Values[idx] = biSunflowerPlains; break; + case biDesert: a_Values[idx] = biDesertM; break; + case biExtremeHills: a_Values[idx] = biExtremeHillsM; break; + case biForest: a_Values[idx] = biFlowerForest; break; + case biTaiga: a_Values[idx] = biTaigaM; break; + case biSwampland: a_Values[idx] = biSwamplandM; break; + case biJungle: a_Values[idx] = biJungleM; break; + case biJungleEdge: a_Values[idx] = biJungleEdgeM; break; + case biBirchForest: a_Values[idx] = biBirchForestM; break; + case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break; + case biRoofedForest: a_Values[idx] = biRoofedForestM; break; + case biColdTaiga: a_Values[idx] = biColdTaigaM; break; + case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break; + case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break; + case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break; + case biSavanna: a_Values[idx] = biSavannaM; break; + case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break; + case biMesa: a_Values[idx] = biMesaBryce; break; + case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break; + case biMesaPlateau: a_Values[idx] = biMesaBryce; break; + } + } // for idx - a_Values[] / alterations[] + } + +protected: + Underlying m_Underlying; + Underlying m_Alteration; +}; + + + + -- cgit v1.2.3 From d5b6353493868ac14b277155f398bd87f08c484c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 2 Nov 2014 16:36:59 +0100 Subject: Grown biomes: Unified with GrownProt biomes. Also fixed a Zoom filter randomness. --- src/Generating/BioGen.cpp | 104 ++++---- src/Generating/IntGen.h | 567 +++++++++++++++++++++++++++++++++++++------- src/Generating/ProtIntGen.h | 83 ++++--- 3 files changed, 595 insertions(+), 159 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index dc5f715ca..0f2b0a73d 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -928,59 +928,77 @@ public: cBioGenGrown(int a_Seed) { auto FinalRivers = - std::make_shared> (a_Seed + 1, - std::make_shared> (a_Seed + 3, - std::make_shared> (a_Seed + 2, - std::make_shared> (a_Seed + 4, - std::make_shared> (a_Seed + 5, - std::make_shared> (a_Seed + 6, - std::make_shared> (a_Seed + 7, - std::make_shared> (a_Seed + 8, - std::make_shared> (a_Seed + 9, - std::make_shared> (a_Seed + 10, - std::make_shared> (a_Seed + 11, - std::make_shared>(a_Seed + 12 - )))))))))))); + std::make_shared> (a_Seed + 1, + std::make_shared> (a_Seed + 2, + std::make_shared> (a_Seed + 3, + std::make_shared> (a_Seed + 4, + std::make_shared> (a_Seed + 5, + std::make_shared> (a_Seed + 8, + std::make_shared> (a_Seed + 5, + std::make_shared> (a_Seed + 9, + std::make_shared> (a_Seed + 5, + std::make_shared> (a_Seed + 10, + std::make_shared> (a_Seed + 5, + std::make_shared> (a_Seed + 6, + std::make_shared> (a_Seed + 11, + std::make_shared>(a_Seed + 12 + )))))))))))))); + + auto alteration = + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, 20 + )); + + auto alteration2 = + std::make_shared>(a_Seed + 1, + std::make_shared>(a_Seed + 2, + std::make_shared>(a_Seed + 1, + std::make_shared>(a_Seed + 2, + std::make_shared>(a_Seed + 1, 10 + ))))); auto FinalBiomes = - std::make_shared> (a_Seed + 1008, - std::make_shared>(a_Seed + 15, - std::make_shared> (a_Seed + 1000, - std::make_shared> (a_Seed + 16, + std::make_shared> (a_Seed + 1, + std::make_shared>(a_Seed + 15, + std::make_shared> (a_Seed + 1, + std::make_shared> (a_Seed + 16, std::make_shared> ( - std::make_shared> (a_Seed + 1002, - std::make_shared>(a_Seed + 1, - std::make_shared> (a_Seed + 1002, - std::make_shared> (a_Seed + 2, + std::make_shared> (a_Seed + 1, std::make_shared> (a_Seed + 2004, 10, - std::make_shared> (a_Seed + 4, - std::make_shared> (a_Seed + 9, 10, biMushroomIsland, - std::make_shared> (biIcePlains, biIcePlainsSpikes, 5, a_Seed + 99, - std::make_shared> (a_Seed + 8, - std::make_shared> (a_Seed + 10, 500, biDeepOcean, - std::make_shared> (a_Seed + 3000, - std::make_shared> (a_Seed + 5, - std::make_shared> ( - std::make_shared> (a_Seed + 1003, - std::make_shared> (a_Seed + 7, + std::make_shared> (a_Seed + 10, 500, biDeepOcean, + std::make_shared> (a_Seed + 1, biPlains, biSunflowerPlains, 20, + std::make_shared> (a_Seed + 5, alteration2, + std::make_shared> (a_Seed + 1, alteration, + std::make_shared> (a_Seed + 3, + std::make_shared>(a_Seed + 2, + std::make_shared> (a_Seed + 4, + std::make_shared> (a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50, + std::make_shared> (a_Seed + 8, + std::make_shared> (a_Seed + 10, 300, biDeepOcean, + std::make_shared> (a_Seed + 9, 8, biMushroomIsland, + std::make_shared> (a_Seed + 3000, + std::make_shared> (a_Seed + 2000, 200, + std::make_shared> (a_Seed + 5, + std::make_shared> (a_Seed + 5, 50, + std::make_shared> ( + std::make_shared> (a_Seed + 2000, 200, + std::make_shared> (a_Seed + 7, std::make_shared> (a_Seed + 8, 50, bgOcean, - std::make_shared> (bgIce, bgTemperate, 50, a_Seed + 101, - std::make_shared> (a_Seed + 2000, 70, + std::make_shared> (a_Seed + 101, bgIce, bgTemperate, 150, + std::make_shared> (a_Seed + 2000, 200, std::make_shared> (a_Seed + 9, 50, bgOcean, - std::make_shared> (a_Seed + 1004, - std::make_shared> (a_Seed + 10, - std::make_shared> (a_Seed + 100, 65 - ))))))))))))))))))))))))))); + std::make_shared> (a_Seed + 10, + std::make_shared> (a_Seed + 100, 30 + ))))))))))))))))))))))))))))))); m_Gen = std::make_shared>(a_Seed, std::make_shared>(a_Seed, - std::make_shared>(a_Seed, - std::make_shared>(a_Seed, - std::make_shared>(a_Seed, - std::make_shared> ( + std::make_shared>(a_Seed, + std::make_shared>(a_Seed, + std::make_shared> ( FinalBiomes, FinalRivers - )))))); + ))))); } virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override @@ -1025,7 +1043,7 @@ public: std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 10, std::make_shared(a_Seed + 5, - std::make_shared(a_Seed + 5, + std::make_shared(a_Seed + 6, std::make_shared(a_Seed + 11, std::make_shared(a_Seed + 12, 2 )))))))))))))); diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 15a5c9157..83a0e569a 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -167,7 +167,7 @@ public: for (int x = 0; x < SizeX; x++) { int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); - a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0; + a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0; } } @@ -186,6 +186,9 @@ protected: +/** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between. +This means that the zoome out image is randomly distorted. Applying zoom several times provides all +the distortion that the generators need. */ template class cIntGenZoom : public cIntGenWithNoise @@ -212,31 +215,30 @@ public: // Generate the underlying data with half the resolution: int lowerMinX = a_MinX >> 1; int lowerMinZ = a_MinZ >> 1; - int Underlying[m_LowerSizeX * m_LowerSizeZ]; - m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, Underlying); + int lowerData[m_LowerSizeX * m_LowerSizeZ]; + m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerData); const int lowStepX = (m_LowerSizeX - 1) * 2; const int lowStepZ = (m_LowerSizeZ - 1) * 2; - int Cache[lowStepX * lowStepZ]; + int cache[lowStepX * lowStepZ]; // Discreet-interpolate the values into twice the size: for (int z = 0; z < m_LowerSizeZ - 1; ++z) { int idx = (z * 2) * lowStepX; - int PrevZ0 = Underlying[z * m_LowerSizeX]; - int PrevZ1 = Underlying[(z + 1) * m_LowerSizeX]; + int PrevZ0 = lowerData[z * m_LowerSizeX]; + int PrevZ1 = lowerData[(z + 1) * m_LowerSizeX]; for (int x = 0; x < m_LowerSizeX - 1; ++x) { - int ValX1Z0 = Underlying[x + 1 + z * m_LowerSizeX]; - int ValX1Z1 = Underlying[x + 1 + (z + 1) * m_LowerSizeX]; + int ValX1Z0 = lowerData[x + 1 + z * m_LowerSizeX]; + int ValX1Z1 = lowerData[x + 1 + (z + 1) * m_LowerSizeX]; int RndX = (x + lowerMinX) * 2; int RndZ = (z + lowerMinZ) * 2; - Cache[idx] = PrevZ0; - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); - idx++; - Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); - idx++; + cache[idx] = PrevZ0; + cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1); + cache[idx + 1] = super::ChooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0); + cache[idx + 1 + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } @@ -245,7 +247,7 @@ public: // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: for (int z = 0; z < SizeZ; ++z) { - memcpy(a_Values + z * SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int)); + memcpy(a_Values + z * SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int)); } } @@ -257,16 +259,18 @@ protected: +/** Smoothes out some artifacts generated by the zooming - mostly single-pixel values. +Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */ template class cIntGenSmooth : public cIntGenWithNoise { typedef cIntGenWithNoise super; - static const int UnderlyingSizeX = SizeX + 2; - static const int UnderlyingSizeZ = SizeZ + 2; + static const int m_LowerSizeX = SizeX + 2; + static const int m_LowerSizeZ = SizeZ + 2; public: - typedef std::shared_ptr> Underlying; + typedef std::shared_ptr> Underlying; cIntGenSmooth(int a_Seed, Underlying a_Underlying) : @@ -279,8 +283,8 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying values: - int Cache[UnderlyingSizeX * UnderlyingSizeZ]; - m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + int lowerData[m_LowerSizeX * m_LowerSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerData); // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. // Also get rid of single-pixel irregularities (A-B-A): @@ -289,33 +293,33 @@ public: int NoiseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { - int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; - int Above = Cache[x + 1 + z * UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; + int val = lowerData[x + 1 + (z + 1) * m_LowerSizeX]; + int above = lowerData[x + 1 + z * m_LowerSizeX]; + int below = lowerData[x + 1 + (z + 2) * m_LowerSizeX]; + int left = lowerData[x + (z + 1) * m_LowerSizeX]; + int right = lowerData[x + 2 + (z + 1) * m_LowerSizeX]; - if ((Left == Right) && (Above == Below)) + if ((left == right) && (above == below)) { if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) { - val = Left; + val = left; } else { - val = Above; + val = above; } } else { - if (Left == Right) + if (left == right) { - val = Left; + val = left; } - if (Above == Below) + if (above == below) { - val = Above; + val = above; } } @@ -332,7 +336,8 @@ protected: -template +/** Converts land biomes at the edge of an ocean into the respective beach biome. */ +template class cIntGenBeaches : public cIntGen { @@ -398,23 +403,24 @@ public: }; // Generate the underlying values: - int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; - m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); + int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); // Add beaches between ocean and biomes: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { - int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; - int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; + int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int above = lowerValues[x + 1 + z * m_UnderlyingSizeX]; + int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX]; + int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX]; if (!IsBiomeOcean(val)) { - if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right)) { + // First convert the value to a regular biome (drop the M flag), then modulo by our biome count: val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; } } @@ -431,7 +437,8 @@ protected: -/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */ +/** Generates the underlying numbers and then randomly changes some ocean group pixels into random land +biome group pixels, based on the predefined chance. */ template class cIntGenAddIslands : public cIntGenWithNoise @@ -442,9 +449,9 @@ public: typedef std::shared_ptr> Underlying; - cIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) : + cIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying) : super(a_Seed), - m_Threshold(a_Threshold), + m_Chance(a_Chance), m_Underlying(a_Underlying) { } @@ -460,17 +467,18 @@ public: if (a_Values[x + z * SizeX] == bgOcean) { int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; - if (rnd % 100 < m_Threshold) + if (rnd % 1000 < m_Chance) { - a_Values[x + z * SizeX] = (rnd / 100) % bgLandOceanMax; + a_Values[x + z * SizeX] = (rnd / 1003) % bgLandOceanMax; } } - } - } + } // for x + } // for z } protected: - int m_Threshold; + /** Chance, in permille, of an island being generated in ocean. */ + int m_Chance; Underlying m_Underlying; }; @@ -502,32 +510,32 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) { // Generate the underlying biome groups: - int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ]; - m_Underlying->GetInts(a_MinX, a_MinZ, Cache); + int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ]; + m_Underlying->GetInts(a_MinX, a_MinZ, lowerValues); // Change the biomes on incompatible edges into an edge biome: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { - int v = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX]; - int Above = Cache[x + 1 + z * m_UnderlyingSizeX]; - int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX]; - int Left = Cache[x + (z + 1) * m_UnderlyingSizeX]; - int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX]; - switch (v) + int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX]; + int above = lowerValues[x + 1 + z * m_UnderlyingSizeX]; + int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX]; + int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX]; + int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX]; + switch (val) { // Desert should neighbor only oceans, desert and temperates; change to temperate when another: case bgDesert: { if ( - !isDesertCompatible(Above) || - !isDesertCompatible(Below) || - !isDesertCompatible(Left) || - !isDesertCompatible(Right) + !isDesertCompatible(above) || + !isDesertCompatible(below) || + !isDesertCompatible(left) || + !isDesertCompatible(right) ) { - v = bgTemperate; + val = bgTemperate; } break; } // case bgDesert @@ -536,18 +544,18 @@ public: case bgIce: { if ( - (Above == bgDesert) || - (Below == bgDesert) || - (Left == bgDesert) || - (Right == bgDesert) + (above == bgDesert) || + (below == bgDesert) || + (left == bgDesert) || + (right == bgDesert) ) { - v = bgTemperate; + val = bgTemperate; } break; } // case bgIce } - a_Values[x + z * SizeX] = v; + a_Values[x + z * SizeX] = val; } // for x } // for z } @@ -578,6 +586,9 @@ protected: +/** Turns biome group indices into real biomes. +For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with +that biome. */ template class cIntGenBiomes : public cIntGenWithNoise @@ -600,7 +611,13 @@ public: // Define the per-biome-group biomes: static const int oceanBiomes[] = { - biOcean, // biDeepOcean, + biOcean, // biDeepOcean, + }; + + // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) + static const int rareOceanBiomes[] = + { + biOcean, }; static const int desertBiomes[] = @@ -608,19 +625,29 @@ public: biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; + static const int rareDesertBiomes[] = + { + biMesaPlateau, biMesaPlateauF, + }; + static const int temperateBiomes[] = { biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; + static const int rareTemperateBiomes[] = + { + biJungle, // Jungle is not strictly temperate, but let's piggyback it here + }; + static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; - static const int jungleBiomes[] = + static const int rareMountainBiomes[] = { - biJungle, biJungle, biJungle, biForest, + biMegaTaiga, }; static const int iceBiomes[] = @@ -628,20 +655,28 @@ public: biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const int mesaBiomes[] = + // Same as iceBiomes, there's no rare ice biome + static const int rareIceBiomes[] = { - biMesa, biMesaPlateau, + biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; - static const cBiomesInGroups BiomesInGroups[] = + static const cBiomesInGroups biomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, - /* bgJungle */ { static_cast(ARRAYCOUNT(jungleBiomes)), jungleBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, - /* bgMesa */ { static_cast(ARRAYCOUNT(mesaBiomes)), mesaBiomes}, + }; + + static const cBiomesInGroups rareBiomesInGroups[] = + { + /* bgOcean */ { static_cast(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes}, + /* bgDesert */ { static_cast(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes}, + /* bgTemperate */ { static_cast(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes}, + /* bgMountains */ { static_cast(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes}, + /* bgIce */ { static_cast(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes}, }; // Generate the underlying values, representing biome groups: @@ -654,7 +689,9 @@ public: for (int x = 0; x < SizeX; x++) { int val = a_Values[x + IdxZ]; - const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)]; + const cBiomesInGroups & Biomes = (val > bgfRare) ? + rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] : + biomesInGroups[val % ARRAYCOUNT(biomesInGroups)]; int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } @@ -678,6 +715,7 @@ protected: +/** Randomly replaces pixels of one value to another value, using the given chance. */ template class cIntGenReplaceRandomly : public cIntGenWithNoise @@ -713,7 +751,7 @@ public: if (a_Values[idx] == m_From) { int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; - if (rnd % 100 < m_Chance) + if (rnd % 1000 < m_Chance) { a_Values[idx] = m_To; } @@ -724,9 +762,15 @@ public: protected: + /** The original value to be replaced. */ int m_From; + + /** The destination value to which to replace. */ int m_To; + + /** Chance, in permille, of replacing the value. */ int m_Chance; + Underlying m_Underlying; }; @@ -735,7 +779,9 @@ protected: /** Mixer that joins together finalized biomes and rivers. -It first checks for oceans; if there's no ocean, it checks for a river. */ +It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean. +If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either +regular river or frozen river, based on the biome. */ template class cIntGenMixRivers: public cIntGen @@ -757,8 +803,8 @@ public: { // Generate the underlying data: m_Biomes->GetInts(a_MinX, a_MinZ, a_Values); - typename super::Values Rivers; - m_Rivers->GetInts(a_MinX, a_MinZ, Rivers); + typename super::Values riverData; + m_Rivers->GetInts(a_MinX, a_MinZ, riverData); // Mix the values: for (int z = 0; z < SizeZ; z++) @@ -772,7 +818,7 @@ public: // Oceans are kept without any changes continue; } - if (Rivers[idx] != biRiver) + if (riverData[idx] != biRiver) { // There's no river, keep the current value continue; @@ -925,7 +971,10 @@ public: } // If at least 3 ocean neighbors and the chance is right, change: - if ((NumOceanNeighbors >= 3) && ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance)) + if ( + (NumOceanNeighbors >= 3) && + ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance) + ) { a_Values[x + z * SizeX] = m_ToValue; } @@ -1003,3 +1052,355 @@ protected: + +/** Adds a "rare" flag to random biome groups, based on the given chance. */ +template +class cIntGenRareBiomeGroups: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying): + super(a_Seed), + m_Chance(a_Chance), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying data: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + + // Change some of the biome groups into rare biome groups: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; + if (rnd % 1000 < m_Chance) + { + int idx = x + SizeX * z; + a_Values[idx] = a_Values[idx] | bgfRare; + } + } + } + } + +protected: + /** Chance, in permille, of changing each pixel into the rare biome group. */ + int m_Chance; + + /** The underlying generator. */ + Underlying m_Underlying; +}; + + + + + +/** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places +that have their alterations set. */ +template +class cIntGenAlternateBiomes: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes): + super(a_Seed), + m_Alterations(a_Alterations), + m_BaseBiomes(a_BaseBiomes) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the base biomes and the alterations: + m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_Values); + super::Values alterations; + m_Alterations->GetInts(a_MinX, a_MinZ, alterations); + + // Change the biomes into their alternate versions: + for (int idx = 0; idx < SizeX * SizeZ; ++idx) + { + if (alterations[idx] == 0) + { + // No change + continue; + } + + // Change to alternate biomes: + int val = a_Values[idx]; + switch (val) + { + case biBirchForest: val = biBirchForestHills; break; + case biDesert: val = biDesertHills; break; + case biExtremeHills: val = biExtremeHillsPlus; break; + case biForest: val = biForestHills; break; + case biIcePlains: val = biIceMountains; break; + case biJungle: val = biJungleHills; break; + case biMegaTaiga: val = biMegaTaigaHills; break; + case biMesaPlateau: val = biMesa; break; + case biMesaPlateauF: val = biMesa; break; + case biMesaPlateauM: val = biMesa; break; + case biMesaPlateauFM: val = biMesa; break; + case biPlains: val = biForest; break; + case biRoofedForest: val = biPlains; break; + case biSavanna: val = biSavannaPlateau; break; + case biTaiga: val = biTaigaHills; break; + } + a_Values[idx] = val; + } // for idx - a_Values[] + } + +protected: + Underlying m_Alterations; + Underlying m_BaseBiomes; +}; + + + + + +/** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */ +template +class cIntGenBiomeEdges: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + static const int m_LowerSizeX = SizeX + 2; + static const int m_LowerSizeZ = SizeZ + 2; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenBiomeEdges(int a_Seed, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying biomes: + Underlying::element_type::Values lowerValues; + m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); + + // Convert incompatible edges into neutral biomes: + for (int z = 0; z < SizeZ; z++) + { + for (int x = 0; x < SizeX; x++) + { + int biome = lowerValues[x + 1 + (z + 1) * m_LowerSizeX]; + int above = lowerValues[x + 1 + z * m_LowerSizeX]; + int below = lowerValues[x + 1 + (z + 2) * m_LowerSizeX]; + int left = lowerValues[x + (z + 1) * m_LowerSizeX]; + int right = lowerValues[x + 2 + (z + 1) * m_LowerSizeX]; + + switch (biome) + { + case biDesert: + case biDesertM: + case biDesertHills: + { + if ( + IsBiomeVeryCold(static_cast(above)) || + IsBiomeVeryCold(static_cast(below)) || + IsBiomeVeryCold(static_cast(left)) || + IsBiomeVeryCold(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // case biDesert + + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + { + if ( + !isMesaCompatible(above) || + !isMesaCompatible(below) || + !isMesaCompatible(left) || + !isMesaCompatible(right) + ) + { + biome = biDesert; + } + break; + } // Mesa biomes + + case biJungle: + case biJungleM: + { + if ( + !isJungleCompatible(above) || + !isJungleCompatible(below) || + !isJungleCompatible(left) || + !isJungleCompatible(right) + ) + { + biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM; + } + break; + } // Jungle biomes + + case biSwampland: + case biSwamplandM: + { + if ( + IsBiomeNoDownfall(static_cast(above)) || + IsBiomeNoDownfall(static_cast(below)) || + IsBiomeNoDownfall(static_cast(left)) || + IsBiomeNoDownfall(static_cast(right)) + ) + { + biome = biPlains; + } + break; + } // Swampland biomes + } // switch (biome) + + a_Values[x + z * SizeX] = biome; + } // for x + } // for z + } + + +protected: + Underlying m_Underlying; + + + bool isMesaCompatible(int a_Biome) + { + switch (a_Biome) + { + case biDesert: + case biMesa: + case biMesaBryce: + case biMesaPlateau: + case biMesaPlateauF: + case biMesaPlateauFM: + case biMesaPlateauM: + case biOcean: + case biDeepOcean: + { + return true; + } + default: + { + return false; + } + } + } + + + bool isJungleCompatible(int a_Biome) + { + switch (a_Biome) + { + case biJungle: + case biJungleM: + case biJungleEdge: + case biJungleEdgeM: + case biJungleHills: + { + return true; + } + default: + { + return false; + } + } + } +}; + + + + + +/** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that +have their alterations set. */ +template +class cIntGenMBiomes: + public cIntGenWithNoise +{ + typedef cIntGenWithNoise super; + +public: + typedef std::shared_ptr> Underlying; + + + cIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying): + super(a_Seed), + m_Underlying(a_Underlying), + m_Alteration(a_Alteration) + { + } + + + virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override + { + // Generate the underlying biomes and the alterations: + m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); + super::Values alterations; + m_Alteration->GetInts(a_MinX, a_MinZ, alterations); + + // Wherever alterations are nonzero, change into alternate biome, if available: + for (int idx = 0; idx < SizeX * SizeZ; ++idx) + { + if (alterations[idx] == 0) + { + continue; + } + + // Ice spikes biome was removed from here, because it was generated way too often + switch (a_Values[idx]) + { + case biPlains: a_Values[idx] = biSunflowerPlains; break; + case biDesert: a_Values[idx] = biDesertM; break; + case biExtremeHills: a_Values[idx] = biExtremeHillsM; break; + case biForest: a_Values[idx] = biFlowerForest; break; + case biTaiga: a_Values[idx] = biTaigaM; break; + case biSwampland: a_Values[idx] = biSwamplandM; break; + case biJungle: a_Values[idx] = biJungleM; break; + case biJungleEdge: a_Values[idx] = biJungleEdgeM; break; + case biBirchForest: a_Values[idx] = biBirchForestM; break; + case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break; + case biRoofedForest: a_Values[idx] = biRoofedForestM; break; + case biColdTaiga: a_Values[idx] = biColdTaigaM; break; + case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break; + case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break; + case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break; + case biSavanna: a_Values[idx] = biSavannaM; break; + case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break; + case biMesa: a_Values[idx] = biMesaBryce; break; + case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break; + case biMesaPlateau: a_Values[idx] = biMesaBryce; break; + } + } // for idx - a_Values[] / alterations[] + } + +protected: + Underlying m_Underlying; + Underlying m_Alteration; +}; + + + + diff --git a/src/Generating/ProtIntGen.h b/src/Generating/ProtIntGen.h index 9c3eb36cc..73ed27096 100644 --- a/src/Generating/ProtIntGen.h +++ b/src/Generating/ProtIntGen.h @@ -70,14 +70,14 @@ protected: cNoise m_Noise; /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ - int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) + int chooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; return ((rnd & 1) == 0) ? a_Val1 : a_Val2; } /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ - int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) + int chooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; switch (rnd % 4) @@ -173,6 +173,9 @@ protected: +/** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between. +This means that the zoome out image is randomly distorted. Applying zoom several times provides all +the distortion that the generators need. */ class cProtIntGenZoom : public cProtIntGenWithNoise { @@ -201,7 +204,7 @@ public: int lowerData[m_BufferSize]; m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerSizeX, lowerSizeZ, lowerData); const int lowStepX = (lowerSizeX - 1) * 2; - int Cache[m_BufferSize]; + int cache[m_BufferSize]; // Discreet-interpolate the values into twice the size: for (int z = 0; z < lowerSizeZ - 1; ++z) @@ -216,12 +219,11 @@ public: int ValX1Z1 = lowerData[x + 1 + (z + 1) * lowerSizeX]; int RndX = (x + lowerMinX) * 2; int RndZ = (z + lowerMinZ) * 2; - Cache[idx] = PrevZ0; - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1); - idx++; - Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0); - Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); - idx++; + cache[idx] = PrevZ0; + cache[idx + lowStepX] = super::chooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1); + cache[idx + 1] = super::chooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0); + cache[idx + 1 + lowStepX] = super::chooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); + idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } @@ -230,7 +232,7 @@ public: // Copy from Cache into a_Values; take into account the even/odd offsets in a_Min: for (int z = 0; z < a_SizeZ; ++z) { - memcpy(a_Values + z * a_SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); + memcpy(a_Values + z * a_SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); } } @@ -242,6 +244,8 @@ protected: +/** Smoothes out some artifacts generated by the zooming - mostly single-pixel values. +Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */ class cProtIntGenSmooth : public cProtIntGenWithNoise { @@ -272,32 +276,32 @@ public: for (int x = 0; x < a_SizeX; x++) { int val = lowerData[x + 1 + (z + 1) * lowerSizeX]; - int Above = lowerData[x + 1 + z * lowerSizeX]; - int Below = lowerData[x + 1 + (z + 2) * lowerSizeX]; - int Left = lowerData[x + (z + 1) * lowerSizeX]; - int Right = lowerData[x + 2 + (z + 1) * lowerSizeX]; + int above = lowerData[x + 1 + z * lowerSizeX]; + int below = lowerData[x + 1 + (z + 2) * lowerSizeX]; + int left = lowerData[x + (z + 1) * lowerSizeX]; + int right = lowerData[x + 2 + (z + 1) * lowerSizeX]; - if ((Left == Right) && (Above == Below)) + if ((left == right) && (above == below)) { if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) { - val = Left; + val = left; } else { - val = Above; + val = above; } } else { - if (Left == Right) + if (left == right) { - val = Left; + val = left; } - if (Above == Below) + if (above == below) { - val = Above; + val = above; } } @@ -314,6 +318,7 @@ protected: +/** Converts land biomes at the edge of an ocean into the respective beach biome. */ class cProtIntGenBeaches : public cProtIntGen { @@ -386,14 +391,15 @@ public: for (int x = 0; x < a_SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; - int Above = lowerValues[x + 1 + z * lowerSizeX]; - int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; - int Left = lowerValues[x + (z + 1) * lowerSizeX]; - int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; + int above = lowerValues[x + 1 + z * lowerSizeX]; + int below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; + int left = lowerValues[x + (z + 1) * lowerSizeX]; + int right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; if (!IsBiomeOcean(val)) { - if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right)) + if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right)) { + // First convert the value to a regular biome (drop the M flag), then modulo by our biome count: val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)]; } } @@ -411,7 +417,7 @@ protected: /** Generates the underlying numbers and then randomly changes some ocean group pixels into random land -group pixels, based on the predefined chance. */ +biome group pixels, based on the predefined chance. */ class cProtIntGenAddIslands : public cProtIntGenWithNoise { @@ -441,7 +447,7 @@ public: int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; if (rnd % 1000 < m_Chance) { - a_Values[x + z * a_SizeX] = (rnd / 101) % bgLandOceanMax; + a_Values[x + z * a_SizeX] = (rnd / 1003) % bgLandOceanMax; } } } @@ -575,7 +581,7 @@ public: // Define the per-biome-group biomes: static const int oceanBiomes[] = { - biOcean, // biDeepOcean, + biOcean, // biDeepOcean, }; // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) @@ -680,6 +686,7 @@ protected: +/** Randomly replaces pixels of one value to another value, using the given chance. */ class cProtIntGenReplaceRandomly : public cProtIntGenWithNoise { @@ -725,9 +732,15 @@ public: protected: + /** The original value to be replaced. */ int m_From; + + /** The destination value to which to replace. */ int m_To; + + /** Chance, in permille, of replacing the value. */ int m_Chance; + Underlying m_Underlying; }; @@ -736,7 +749,9 @@ protected: /** Mixer that joins together finalized biomes and rivers. -It first checks for oceans; if there's no ocean, it checks for a river. */ +It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean. +If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either +regular river or frozen river, based on the biome. */ class cProtIntGenMixRivers: public cProtIntGen { @@ -1043,8 +1058,8 @@ protected: -/** Changes biomes in the parent data into their alternate verions ("M" variants), in such places that -have their alterations set. */ +/** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places +that have their alterations set. */ class cProtIntGenAlternateBiomes: public cProtIntGenWithNoise { @@ -1080,7 +1095,7 @@ public: int val = a_Values[idx]; switch (val) { - case biBirchForest: val = biBirchForest; break; + case biBirchForest: val = biBirchForestHills; break; case biDesert: val = biDesertHills; break; case biExtremeHills: val = biExtremeHillsPlus; break; case biForest: val = biForestHills; break; @@ -1267,6 +1282,8 @@ protected: +/** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that +have their alterations set. */ class cProtIntGenMBiomes: public cProtIntGenWithNoise { -- cgit v1.2.3 From dbed5c0726f69a2ff43a869491d93030d6d9c742 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 2 Nov 2014 16:47:56 +0100 Subject: Grown biomes: fixed Linux build. --- src/Generating/IntGen.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h index 83a0e569a..b25e378c0 100644 --- a/src/Generating/IntGen.h +++ b/src/Generating/IntGen.h @@ -1128,7 +1128,7 @@ public: { // Generate the base biomes and the alterations: m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_Values); - super::Values alterations; + typename super::Values alterations; m_Alterations->GetInts(a_MinX, a_MinZ, alterations); // Change the biomes into their alternate versions: @@ -1196,7 +1196,7 @@ public: virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override { // Generate the underlying biomes: - Underlying::element_type::Values lowerValues; + typename Underlying::element_type::Values lowerValues; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); // Convert incompatible edges into neutral biomes: @@ -1358,7 +1358,7 @@ public: { // Generate the underlying biomes and the alterations: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); - super::Values alterations; + typename super::Values alterations; m_Alteration->GetInts(a_MinX, a_MinZ, alterations); // Wherever alterations are nonzero, change into alternate biome, if available: -- cgit v1.2.3 From ca296837386f428c50206ccdea4ba63ce014f8a3 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 3 Nov 2014 08:17:19 +0100 Subject: HeiGen: Moved construction to the end of file. This will allow us to define generators in the cpp file instead of needing them in the header, thus speeding up compilation on changes. --- src/Generating/HeiGen.cpp | 150 +++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 75 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index f4e231470..f7a26544c 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -16,81 +16,6 @@ -//////////////////////////////////////////////////////////////////////////////// -// cTerrainHeightGen: - -cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault) -{ - AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", ""); - if (HeightGenName.empty()) - { - LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\"."); - HeightGenName = "Biomal"; - } - - a_CacheOffByDefault = false; - cTerrainHeightGen * res = nullptr; - if (NoCaseCompare(HeightGenName, "flat") == 0) - { - res = new cHeiGenFlat; - a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data - } - else if (NoCaseCompare(HeightGenName, "classic") == 0) - { - res = new cHeiGenClassic(a_Seed); - } - else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0) - { - res = new cDistortedHeightmap(a_Seed, a_BiomeGen); - } - else if (NoCaseCompare(HeightGenName, "End") == 0) - { - res = new cEndGen(a_Seed); - } - else if (NoCaseCompare(HeightGenName, "Mountains") == 0) - { - res = new cHeiGenMountains(a_Seed); - } - else if (NoCaseCompare(HeightGenName, "Noise3D") == 0) - { - res = new cNoise3DComposable(a_Seed); - } - else if (NoCaseCompare(HeightGenName, "biomal") == 0) - { - res = new cHeiGenBiomal(a_Seed, a_BiomeGen); - - /* - // Performance-testing: - LOGINFO("Measuring performance of cHeiGenBiomal..."); - clock_t BeginTick = clock(); - for (int x = 0; x < 500; x++) - { - cChunkDef::HeightMap Heights; - res->GenHeightMap(x * 5, x * 5, Heights); - } - clock_t Duration = clock() - BeginTick; - LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); - //*/ - } - else - { - // No match found, force-set the default and retry - LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str()); - a_IniFile.DeleteValue("Generator", "HeightGen"); - a_IniFile.SetValue("Generator", "HeightGen", "Biomal"); - return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); - } - - // Read the settings: - res->InitializeHeightGen(a_IniFile); - - return cTerrainHeightGenPtr(res); -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cHeiGenFlat: @@ -611,3 +536,78 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, +//////////////////////////////////////////////////////////////////////////////// +// cTerrainHeightGen: + +cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault) +{ + AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", ""); + if (HeightGenName.empty()) + { + LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\"."); + HeightGenName = "Biomal"; + } + + a_CacheOffByDefault = false; + cTerrainHeightGen * res = nullptr; + if (NoCaseCompare(HeightGenName, "flat") == 0) + { + res = new cHeiGenFlat; + a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data + } + else if (NoCaseCompare(HeightGenName, "classic") == 0) + { + res = new cHeiGenClassic(a_Seed); + } + else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0) + { + res = new cDistortedHeightmap(a_Seed, a_BiomeGen); + } + else if (NoCaseCompare(HeightGenName, "End") == 0) + { + res = new cEndGen(a_Seed); + } + else if (NoCaseCompare(HeightGenName, "Mountains") == 0) + { + res = new cHeiGenMountains(a_Seed); + } + else if (NoCaseCompare(HeightGenName, "Noise3D") == 0) + { + res = new cNoise3DComposable(a_Seed); + } + else if (NoCaseCompare(HeightGenName, "biomal") == 0) + { + res = new cHeiGenBiomal(a_Seed, a_BiomeGen); + + /* + // Performance-testing: + LOGINFO("Measuring performance of cHeiGenBiomal..."); + clock_t BeginTick = clock(); + for (int x = 0; x < 500; x++) + { + cChunkDef::HeightMap Heights; + res->GenHeightMap(x * 5, x * 5, Heights); + } + clock_t Duration = clock() - BeginTick; + LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); + //*/ + } + else + { + // No match found, force-set the default and retry + LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str()); + a_IniFile.DeleteValue("Generator", "HeightGen"); + a_IniFile.SetValue("Generator", "HeightGen", "Biomal"); + return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); + } + + // Read the settings: + res->InitializeHeightGen(a_IniFile); + + return cTerrainHeightGenPtr(res); +} + + + + + -- cgit v1.2.3 From f5c4a6a27d7c35afbbb57e0798d1473e2795ca22 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 3 Nov 2014 10:36:12 +0100 Subject: Added a (disabled) perf test for biome generators. --- src/Generating/BioGen.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 0f2b0a73d..5480d8d4c 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -5,6 +5,8 @@ #include "Globals.h" #include "BioGen.h" +#include +#include #include "IntGen.h" #include "ProtIntGen.h" #include "../IniFile.h" @@ -1199,3 +1201,47 @@ cBiomeGenPtr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & + +//////////////////////////////////////////////////////////////////////////////// +// Performance tests: + +// Change to 1 to enable the perf test: +#if 0 + +class cBioGenPerfTest +{ +public: + cBioGenPerfTest() + { + std::cout << "BioGen performance tests commencing, please wait..." << std::endl; + TestGen("MultiStepMap", std::make_unique(1).get()); + TestGen("Grown", std::make_unique(1).get()); + TestGen("GrownProt", std::make_unique(1).get()); + std::cout << "BioGen performance tests complete." << std::endl; + } + +protected: + void TestGen(const AString && a_GenName, cBiomeGen * a_BioGen) + { + // Initialize the default settings for the generator: + cIniFile iniFile; + a_BioGen->InitializeBiomeGen(iniFile); + + // Generate the biomes: + auto start = std::chrono::system_clock::now(); + for (int z = 0; z < 100; z++) + { + for (int x = 0; x < 100; x++) + { + cChunkDef::BiomeMap biomes; + a_BioGen->GenBiomes(x, z, biomes); + } // for x + } // for z + auto dur = std::chrono::system_clock::now() - start; + double milliseconds = static_cast((std::chrono::duration_cast(dur)).count()); + + std::cout << a_GenName << ": " << 1000.0 * 100.0 * 100.0 / milliseconds << " chunks per second" << std::endl; + } +} g_BioGenPerfTest; + +#endif \ No newline at end of file -- cgit v1.2.3 From c5f3663bea6e24226217fe91402704a04f118831 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 3 Nov 2014 11:48:03 +0100 Subject: Fixed a missing endline. --- src/Generating/BioGen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 5480d8d4c..2a4dbe794 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -1244,4 +1244,8 @@ protected: } } g_BioGenPerfTest; -#endif \ No newline at end of file +#endif + + + + -- cgit v1.2.3 From f239a28d0661cbcfa7480d81008bb66607e55742 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Tue, 4 Nov 2014 08:40:23 +0100 Subject: Added MinMax height generator. Fixes #1578. --- src/Generating/HeiGen.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index f7a26544c..de97bc1a0 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -536,6 +536,209 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, +//////////////////////////////////////////////////////////////////////////////// +// cHeiGenMinMax: + +class cHeiGenMinMax: + public cTerrainHeightGen +{ + typedef cTerrainHeightGen super; + + /** Size of the averaging process, in columns (for each direction). Must be less than 16. */ + static const int AVERAGING_SIZE = 4; + +public: + cHeiGenMinMax(int a_Seed, cBiomeGenPtr a_BiomeGen): + m_Noise(a_Seed), + m_BiomeGen(a_BiomeGen), + m_TotalWeight(0) + { + // Initialize the weights: + for (int z = 0; z <= AVERAGING_SIZE * 2; z++) + { + for (int x = 0; x <= AVERAGING_SIZE * 2; x++) + { + m_Weights[z][x] = 1 + 2 * AVERAGING_SIZE - std::abs(x - AVERAGING_SIZE) - std::abs(z - AVERAGING_SIZE); + m_TotalWeight += m_Weights[z][x]; + } + } + + // Initialize the Perlin generator: + m_Perlin.AddOctave(0.04f, 0.2f); + m_Perlin.AddOctave(0.02f, 0.1f); + m_Perlin.AddOctave(0.01f, 0.05f); + m_Perlin.AddOctave(0.005f, 0.025f); + m_Perlin.AddOctave(0.0025f, 0.0125f); + } + + + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) + { + // Generate the biomes for the 3*3 neighbors: + cChunkDef::BiomeMap neighborBiomes[3][3]; + for (int z = 0; z < 3; z++) for (int x = 0; x < 3; x++) + { + m_BiomeGen->GenBiomes(a_ChunkX + x - 1, a_ChunkZ + z - 1, neighborBiomes[z][x]); + } + + // Get the min and max heights based on the biomes: + double minHeight[cChunkDef::Width * cChunkDef::Width]; + double maxHeight[cChunkDef::Width * cChunkDef::Width]; + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + // For each column, sum the min and max values of the neighborhood around it: + double min = 0, max = 0; + for (int relz = 0; relz <= AVERAGING_SIZE * 2; relz++) + { + int bz = z + 16 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start + int cz = bz / 16; // Chunk Z coord relative to the neighborBiomes start + bz = bz % 16; // Biome Z coord relative to cz in neighborBiomes + for (int relx = 0; relx <= AVERAGING_SIZE * 2; relx++) + { + int bx = x + 16 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start + int cx = bx / 16; // Chunk X coord relative to the neighborBiomes start + bx = bx % 16; // Biome X coord relative to cz in neighborBiomes + + // Get the biome's min and max heights: + double bmin, bmax; + getBiomeMinMax(cChunkDef::GetBiome(neighborBiomes[cz][cx], bx, bz), bmin, bmax); + + // Add them to the total, with the weight depending on their relative position to the column: + min += bmin * m_Weights[relz][relx]; + max += bmax * m_Weights[relz][relx]; + } // for relx + } // for relz + minHeight[x + z * cChunkDef::Width] = min / m_TotalWeight; + maxHeight[x + z * cChunkDef::Width] = max / m_TotalWeight; + } // for x + } // for z + + // Generate the base noise: + NOISE_DATATYPE noise[cChunkDef::Width * cChunkDef::Width]; + NOISE_DATATYPE workspace[cChunkDef::Width * cChunkDef::Width]; + NOISE_DATATYPE startX = static_cast(a_ChunkX * cChunkDef::Width); + NOISE_DATATYPE endX = startX + cChunkDef::Width - 1; + NOISE_DATATYPE startZ = static_cast(a_ChunkZ * cChunkDef::Width); + NOISE_DATATYPE endZ = startZ + cChunkDef::Width - 1; + m_Perlin.Generate2D(noise, 16, 16, startX, endX, startZ, endZ, workspace); + + // Make the height by ranging the noise between min and max: + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + double min = minHeight[x + z * cChunkDef::Width]; + double max = maxHeight[x + z * cChunkDef::Width]; + double h = (max + min) / 2 + noise[x + z * cChunkDef::Width] * (max - min); + cChunkDef::SetHeight(a_HeightMap, x, z, static_cast(h)); + } + } + } + + + virtual void InitializeHeightGen(cIniFile & a_IniFile) + { + // No settings available + } + +protected: + cNoise m_Noise; + + cPerlinNoise m_Perlin; + + /** The biome generator to query for the underlying biomes. */ + cBiomeGenPtr m_BiomeGen; + + /** Weights applied to each of the min / max values in the neighborhood of the currently evaluated column. */ + double m_Weights[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1]; + + /** Sum of all the m_Weights items. */ + double m_TotalWeight; + + + /** Returns the minimum and maximum heights for the given biome. */ + void getBiomeMinMax(EMCSBiome a_Biome, double & a_Min, double & a_Max) + { + switch (a_Biome) + { + case biBeach: a_Min = 61; a_Max = 64; break; + case biBirchForest: a_Min = 63; a_Max = 75; break; + case biBirchForestHills: a_Min = 63; a_Max = 90; break; + case biBirchForestHillsM: a_Min = 63; a_Max = 90; break; + case biBirchForestM: a_Min = 63; a_Max = 75; break; + case biColdBeach: a_Min = 61; a_Max = 64; break; + case biColdTaiga: a_Min = 63; a_Max = 75; break; + case biColdTaigaHills: a_Min = 63; a_Max = 90; break; + case biColdTaigaM: a_Min = 63; a_Max = 75; break; + case biDeepOcean: a_Min = 30; a_Max = 60; break; + case biDesert: a_Min = 63; a_Max = 70; break; + case biDesertHills: a_Min = 63; a_Max = 85; break; + case biDesertM: a_Min = 63; a_Max = 70; break; + case biEnd: a_Min = 10; a_Max = 100; break; + case biExtremeHills: a_Min = 60; a_Max = 120; break; + case biExtremeHillsEdge: a_Min = 63; a_Max = 100; break; + case biExtremeHillsM: a_Min = 60; a_Max = 120; break; + case biExtremeHillsPlus: a_Min = 60; a_Max = 140; break; + case biExtremeHillsPlusM: a_Min = 60; a_Max = 140; break; + case biFlowerForest: a_Min = 63; a_Max = 75; break; + case biForest: a_Min = 63; a_Max = 75; break; + case biForestHills: a_Min = 63; a_Max = 90; break; + case biFrozenOcean: a_Min = 45; a_Max = 64; break; + case biFrozenRiver: a_Min = 60; a_Max = 62; break; + case biIceMountains: a_Min = 63; a_Max = 90; break; + case biIcePlains: a_Min = 63; a_Max = 70; break; + case biIcePlainsSpikes: a_Min = 60; a_Max = 70; break; + case biJungle: a_Min = 60; a_Max = 80; break; + case biJungleEdge: a_Min = 62; a_Max = 75; break; + case biJungleEdgeM: a_Min = 62; a_Max = 75; break; + case biJungleHills: a_Min = 60; a_Max = 90; break; + case biJungleM: a_Min = 60; a_Max = 75; break; + case biMegaSpruceTaiga: a_Min = 63; a_Max = 75; break; + case biMegaSpruceTaigaHills: a_Min = 63; a_Max = 90; break; + case biMegaTaiga: a_Min = 63; a_Max = 75; break; + case biMegaTaigaHills: a_Min = 63; a_Max = 90; break; + case biMesa: a_Min = 63; a_Max = 90; break; + case biMesaBryce: a_Min = 60; a_Max = 67; break; + case biMesaPlateau: a_Min = 75; a_Max = 85; break; + case biMesaPlateauF: a_Min = 80; a_Max = 90; break; + case biMesaPlateauFM: a_Min = 80; a_Max = 90; break; + case biMesaPlateauM: a_Min = 75; a_Max = 85; break; + case biMushroomIsland: a_Min = 63; a_Max = 90; break; + case biMushroomShore: a_Min = 60; a_Max = 75; break; + case biNether: a_Min = 10; a_Max = 100; break; + case biOcean: a_Min = 45; a_Max = 64; break; + case biPlains: a_Min = 63; a_Max = 70; break; + case biRiver: a_Min = 60; a_Max = 62; break; + case biRoofedForest: a_Min = 63; a_Max = 75; break; + case biRoofedForestM: a_Min = 63; a_Max = 75; break; + case biSavanna: a_Min = 63; a_Max = 75; break; + case biSavannaM: a_Min = 63; a_Max = 80; break; + case biSavannaPlateau: a_Min = 75; a_Max = 100; break; + case biSavannaPlateauM: a_Min = 80; a_Max = 160; break; + case biStoneBeach: a_Min = 60; a_Max = 64; break; + case biSunflowerPlains: a_Min = 63; a_Max = 70; break; + case biSwampland: a_Min = 60; a_Max = 67; break; + case biSwamplandM: a_Min = 61; a_Max = 67; break; + case biTaiga: a_Min = 63; a_Max = 75; break; + case biTaigaHills: a_Min = 63; a_Max = 90; break; + case biTaigaM: a_Min = 63; a_Max = 80; break; + default: + { + ASSERT(!"Unknown biome"); + a_Min = 10; + a_Max = 10; + break; + } + } + } +}; + + + + + //////////////////////////////////////////////////////////////////////////////// // cTerrainHeightGen: @@ -567,6 +770,10 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB { res = new cEndGen(a_Seed); } + else if (NoCaseCompare(HeightGenName, "MinMax") == 0) + { + res = new cHeiGenMinMax(a_Seed, a_BiomeGen); + } else if (NoCaseCompare(HeightGenName, "Mountains") == 0) { res = new cHeiGenMountains(a_Seed); -- cgit v1.2.3 From 7d2b2f90b6190d8fb5280ba0dd43671cd3012f20 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Tue, 4 Nov 2014 08:41:18 +0100 Subject: MinMax heigen: Reduced the number of octaves. They didn't affect the terrain that much anyway. --- src/Generating/HeiGen.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index de97bc1a0..28a5698e4 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -567,8 +567,6 @@ public: m_Perlin.AddOctave(0.04f, 0.2f); m_Perlin.AddOctave(0.02f, 0.1f); m_Perlin.AddOctave(0.01f, 0.05f); - m_Perlin.AddOctave(0.005f, 0.025f); - m_Perlin.AddOctave(0.0025f, 0.0125f); } -- cgit v1.2.3 From 136d6b5c3080df039a5be047c27911c2d03c9fc5 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 6 Nov 2014 19:25:42 +0100 Subject: Noise3D CompoGen: Fixed missing initialization. --- src/Generating/Noise3DGenerator.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 42f61a854..c59b3f933 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -96,9 +96,11 @@ protected: // cTerrainHeightGen overrides: virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } } ; -- cgit v1.2.3 From c43391fd8cfb50746493c103e504d38359c366b2 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 9 Nov 2014 14:33:37 +0100 Subject: Noise3D generator: rewritten from scratch. Now it uses three 3D and one 2D perlin noises to generate the terrain, and is highly parametrizable. --- src/Generating/Noise3DGenerator.cpp | 177 +++++++++++++++++++++--------------- src/Generating/Noise3DGenerator.h | 46 ++++++++-- 2 files changed, 145 insertions(+), 78 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 5a4cb44cf..4292c66e5 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -61,6 +61,35 @@ public: +/** Linearly interpolates between two values. +Assumes that a_Ratio is in range [0, 1]. */ +inline static NOISE_DATATYPE Lerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio) +{ + return a_Val1 + (a_Val2 - a_Val1) * a_Ratio; +} + + + + + +/** Linearly interpolates between two values, clamping the ratio to [0, 1] first. */ +inline static NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio) +{ + if (a_Ratio < 0) + { + return a_Val1; + } + if (a_Ratio > 1) + { + return a_Val2; + } + return a_Val1 + (a_Val2 - a_Val1) * a_Ratio; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cNoise3DGenerator: @@ -346,9 +375,10 @@ void cNoise3DGenerator::ComposeTerrain(cChunkDesc & a_ChunkDesc) // cNoise3DComposable: cNoise3DComposable::cNoise3DComposable(int a_Seed) : - m_Noise1(a_Seed + 1000), - m_Noise2(a_Seed + 2000), - m_Noise3(a_Seed + 3000) + m_ChoiceNoise(a_Seed), + m_DensityNoiseA(a_Seed + 1), + m_DensityNoiseB(a_Seed + 2), + m_BaseNoise(a_Seed + 3) { } @@ -359,13 +389,51 @@ cNoise3DComposable::cNoise3DComposable(int a_Seed) : void cNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: + // The defaults generate extreme hills terrain m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62); - m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0); + m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.045); m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75); - m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 10); - m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 10); - m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 10); - m_AirThreshold = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0.5); + m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 40); + m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 40); + m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 40); + m_BaseFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyX", 40); + m_BaseFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyZ", 40); + m_ChoiceFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyX", 40); + m_ChoiceFrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyY", 80); + m_ChoiceFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyZ", 40); + m_AirThreshold = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0); + int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumChoiceOctaves", 4); + int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumDensityOctaves", 6); + int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumBaseOctaves", 6); + NOISE_DATATYPE BaseNoiseAmplitude = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DBaseAmplitude", 1); + + // Add octaves for the choice noise: + NOISE_DATATYPE wavlen = 1, ampl = 0.5; + for (int i = 0; i < NumChoiceOctaves; i++) + { + m_ChoiceNoise.AddOctave(wavlen, ampl); + wavlen = wavlen * 2; + ampl = ampl / 2; + } + + // Add octaves for the density noises: + wavlen = 1, ampl = 1; + for (int i = 0; i < NumDensityOctaves; i++) + { + m_DensityNoiseA.AddOctave(wavlen, ampl); + m_DensityNoiseB.AddOctave(wavlen, ampl); + wavlen = wavlen * 2; + ampl = ampl / 2; + } + + // Add octaves for the base noise: + wavlen = 1, ampl = BaseNoiseAmplitude; + for (int i = 0; i < NumBaseOctaves; i++) + { + m_BaseNoise.AddOctave(wavlen, ampl); + wavlen = wavlen * 2; + ampl = ampl / 2; + } } @@ -382,77 +450,44 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) m_LastChunkX = a_ChunkX; m_LastChunkZ = a_ChunkZ; - // Upscaling parameters: - const int UPSCALE_X = 8; - const int UPSCALE_Y = 4; - const int UPSCALE_Z = 8; - - // Precalculate a "height" array: - NOISE_DATATYPE Height[17 * 17]; // x + 17 * z - for (int z = 0; z < 17; z += UPSCALE_Z) + // Generate all the noises: + NOISE_DATATYPE ChoiceNoise[5 * 5 * 33]; + NOISE_DATATYPE Workspace[5 * 5 * 33]; + NOISE_DATATYPE DensityNoiseA[5 * 5 * 33]; + NOISE_DATATYPE DensityNoiseB[5 * 5 * 33]; + NOISE_DATATYPE BaseNoise[5 * 5]; + NOISE_DATATYPE BlockX = static_cast(a_ChunkX * cChunkDef::Width); + NOISE_DATATYPE BlockZ = static_cast(a_ChunkZ * cChunkDef::Width); + // Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z": + m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace); + m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); + + // Calculate the final noise based on the partial noises: + for (int y = 0; y < 33; y++) { - NOISE_DATATYPE NoiseZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + z)) / m_FrequencyZ; - for (int x = 0; x < 17; x += UPSCALE_X) - { - NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX; - NOISE_DATATYPE val = std::abs(m_Noise1.CubicNoise2D(NoiseX / 5, NoiseZ / 5)) * m_HeightAmplification + 1; - Height[x + 17 * z] = val * val * val; - } - } + NOISE_DATATYPE AddHeight = (static_cast(y * 8) - m_MidPoint) * m_HeightAmplification; - for (int y = 0; y < 257; y += UPSCALE_Y) - { - NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)y) / m_FrequencyY; - NOISE_DATATYPE AddHeight = (y - m_MidPoint) / 20; - AddHeight *= AddHeight * AddHeight; - NOISE_DATATYPE * CurFloor = &(m_NoiseArray[y * 17 * 17]); - for (int z = 0; z < 17; z += UPSCALE_Z) + // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: + if (AddHeight < 0) { - NOISE_DATATYPE NoiseZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + z)) / m_FrequencyZ; - for (int x = 0; x < 17; x += UPSCALE_X) - { - NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX; - CurFloor[x + 17 * z] = ( - m_Noise1.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * (NOISE_DATATYPE)0.5 + - m_Noise2.CubicNoise3D(NoiseX / 2, NoiseY / 2, NoiseZ / 2) + - m_Noise3.CubicNoise3D(NoiseX / 4, NoiseY / 4, NoiseZ / 4) * 2 + - AddHeight / Height[x + 17 * z] - ); - } + AddHeight *= 4; } - // Linear-interpolate this XZ floor: - LinearUpscale2DArrayInPlace<17, 17, UPSCALE_X, UPSCALE_Z>(CurFloor); - } - // Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis - for (int y = 1; y < cChunkDef::Height; y++) - { - if ((y % UPSCALE_Y) == 0) + for (int z = 0; z < 5; z++) { - // This is the interpolation source floor, already calculated - continue; - } - int LoFloorY = (y / UPSCALE_Y) * UPSCALE_Y; - int HiFloorY = LoFloorY + UPSCALE_Y; - NOISE_DATATYPE * LoFloor = &(m_NoiseArray[LoFloorY * 17 * 17]); - NOISE_DATATYPE * HiFloor = &(m_NoiseArray[HiFloorY * 17 * 17]); - NOISE_DATATYPE * CurFloor = &(m_NoiseArray[y * 17 * 17]); - NOISE_DATATYPE Ratio = ((NOISE_DATATYPE)(y % UPSCALE_Y)) / UPSCALE_Y; - int idx = 0; - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) + for (int x = 0; x < 5; x++) { - CurFloor[idx] = LoFloor[idx] + (HiFloor[idx] - LoFloor[idx]) * Ratio; - idx += 1; + int idx = x + 5 * z + 5 * 5 * y; + Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z]; } - idx += 1; // Skipping one X column } } + LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); - // The noise array is now fully interpolated - /* - // DEBUG: Output two images of the array, sliced by XY and XZ: + #if 0 + // DEBUG: Output two images of m_NoiseArray, sliced by XY and XZ, into grayscale files, to be inspected by Grabber: cFile f1; if (f1.Open(Printf("Chunk_%d_%d_XY.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite)) { @@ -464,7 +499,7 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) unsigned char buf[16]; for (int x = 0; x < cChunkDef::Width; x++) { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 128 * m_Noise[idx++])))); + buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * m_NoiseArray[idx++])))); } f1.Write(buf, 16); } // for y @@ -482,13 +517,13 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) unsigned char buf[16]; for (int x = 0; x < cChunkDef::Width; x++) { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 128 * m_Noise[idx++])))); + buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * m_NoiseArray[idx++])))); } f2.Write(buf, 16); } // for z } // for y } // if (XZ file open) - */ + #endif } diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index c59b3f933..207aeab97 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -1,7 +1,11 @@ // Noise3DGenerator.h -// Generates terrain using 3D noise, rather than composing. Is a test. +// Declares cNoise3DGenerator and cNoise3DComposable classes, representing 3D-noise-based generators. +// They generate terrain shape by combining a lerp of two 3D noises with a vertical linear gradient +// cNoise3DGenerator is obsolete and unmaintained. +// cNoise3DComposable is used to test parameter combinations for single-biome worlds. + @@ -74,24 +78,52 @@ public: void Initialize(cIniFile & a_IniFile); protected: - cNoise m_Noise1; - cNoise m_Noise2; - cNoise m_Noise3; + /** The noise that is used to choose between density noise A and B. */ + cPerlinNoise m_ChoiceNoise; + + /** Density 3D noise, variant A. */ + cPerlinNoise m_DensityNoiseA; + + /** Density 3D noise, variant B. */ + cPerlinNoise m_DensityNoiseB; + + /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ + cPerlinNoise m_BaseNoise; - int m_SeaLevel; + /** Block height of the sealevel, used for composing the terrain. */ + int m_SeaLevel; + + /** 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; - NOISE_DATATYPE m_MidPoint; // Where the vertical "center" of the noise should be + + /** Where the vertical "center" of the noise should be, as block height. */ + NOISE_DATATYPE m_MidPoint; + + // Frequency of the 3D noise's first octave: NOISE_DATATYPE m_FrequencyX; NOISE_DATATYPE m_FrequencyY; NOISE_DATATYPE m_FrequencyZ; + + // Frequency of the base terrain noise: + NOISE_DATATYPE m_BaseFrequencyX; + NOISE_DATATYPE m_BaseFrequencyZ; + + // Frequency of the choice noise: + NOISE_DATATYPE m_ChoiceFrequencyX; + NOISE_DATATYPE m_ChoiceFrequencyY; + NOISE_DATATYPE m_ChoiceFrequencyZ; + + // 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, unless the LastChunk coords are equal to coords given + /** 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: -- cgit v1.2.3 From 5993c06bd7ab5f02aabb4790570c86699189e219 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 9 Nov 2014 15:33:01 +0100 Subject: Noise3d Generator: Fixed unused function error. --- src/Generating/Noise3DGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 4292c66e5..885a9bab3 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -83,7 +83,7 @@ inline static NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a { return a_Val2; } - return a_Val1 + (a_Val2 - a_Val1) * a_Ratio; + return Lerp(a_Val1, a_Val2, a_Ratio); } -- cgit v1.2.3 From 4b95f7c69a1b3a3aac8855d5e026238ed0f61fa7 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 10 Nov 2014 17:00:14 +0100 Subject: Added BiomalNoise3D shape generator. --- src/Generating/ComposableGenerator.cpp | 4 + src/Generating/HeiGen.cpp | 4 + src/Generating/Noise3DGenerator.cpp | 304 +++++++++++++++++++++++++++++---- src/Generating/Noise3DGenerator.h | 86 ++++++++++ 4 files changed, 369 insertions(+), 29 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 169821050..5f46574c7 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -73,6 +73,10 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile { res = new cCompoGenNether(a_Seed); } + else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) + { + res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen); + } else if (NoCaseCompare(CompoGenName, "Noise3D") == 0) { res = new cNoise3DComposable(a_Seed); diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 28a5698e4..1d9f1e3aa 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -776,6 +776,10 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB { res = new cHeiGenMountains(a_Seed); } + else if (NoCaseCompare(HeightGenName, "BiomalNoise3D") == 0) + { + res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen); + } else if (NoCaseCompare(HeightGenName, "Noise3D") == 0) { res = new cNoise3DComposable(a_Seed); diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 885a9bab3..3f50ea0e9 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -444,7 +444,7 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) { if ((a_ChunkX == m_LastChunkX) && (a_ChunkZ == m_LastChunkZ)) { - // The noise for this chunk is already generated in m_Noise + // The noise for this chunk is already generated in m_NoiseArray return; } m_LastChunkX = a_ChunkX; @@ -485,52 +485,298 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) } } LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); +} - #if 0 - // DEBUG: Output two images of m_NoiseArray, sliced by XY and XZ, into grayscale files, to be inspected by Grabber: - cFile f1; - if (f1.Open(Printf("Chunk_%d_%d_XY.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite)) + + + + +void cNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +{ + GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); + + for (int z = 0; z < cChunkDef::Width; z++) { - for (int z = 0; z < cChunkDef::Width; z++) + for (int x = 0; x < cChunkDef::Width; x++) { - for (int y = 0; y < cChunkDef::Height; y++) + cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel); + for (int y = cChunkDef::Height - 1; y > m_SeaLevel; y--) { - int idx = y * 17 * 17 + z * 17; - unsigned char buf[16]; - for (int x = 0; x < cChunkDef::Width; x++) + if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= m_AirThreshold) { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * m_NoiseArray[idx++])))); + cChunkDef::SetHeight(a_HeightMap, x, z, y); + break; } - f1.Write(buf, 16); } // for y - } // for z - } // if (XY file open) + } // for x + } // for z +} - cFile f2; - if (f2.Open(Printf("Chunk_%d_%d_XZ.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite)) + + + + +void cNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) +{ + GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); + + a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); + + // Make basic terrain composition: + for (int z = 0; z < cChunkDef::Width; z++) { - for (int y = 0; y < cChunkDef::Height; y++) + for (int x = 0; x < cChunkDef::Width; x++) { - for (int z = 0; z < cChunkDef::Width; z++) + int LastAir = a_ChunkDesc.GetHeight(x, z) + 1; + bool HasHadWater = false; + for (int y = LastAir; y < m_SeaLevel; y++) { - int idx = y * 17 * 17 + z * 17; - unsigned char buf[16]; - for (int x = 0; x < cChunkDef::Width; x++) + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); + } + for (int y = LastAir - 1; y > 0; y--) + { + if (m_NoiseArray[x + 17 * z + 17 * 17 * y] > m_AirThreshold) { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * m_NoiseArray[idx++])))); + // "air" part + LastAir = y; + if (y < m_SeaLevel) + { + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); + HasHadWater = true; + } + continue; } - f2.Write(buf, 16); - } // for z - } // for y - } // if (XZ file open) - #endif + // "ground" part: + if (LastAir - y > 4) + { + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE); + continue; + } + if (HasHadWater) + { + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND); + } + else + { + a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); + } + } // for y + a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); + } // for x + } // for z } -void cNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +//////////////////////////////////////////////////////////////////////////////// +// cBiomalNoise3DComposable: + +cBiomalNoise3DComposable::cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_BiomeGen) : + m_ChoiceNoise(a_Seed), + m_DensityNoiseA(a_Seed + 1), + m_DensityNoiseB(a_Seed + 2), + m_BaseNoise(a_Seed + 3), + m_BiomeGen(a_BiomeGen) +{ + // Generate the weight distribution for summing up neighboring biomes: + m_WeightSum = 0; + for (int z = 0; z <= AVERAGING_SIZE * 2; z++) + { + for (int x = 0; x <= AVERAGING_SIZE * 2; x++) + { + m_Weight[z][x] = static_cast((5 - std::abs(5 - x)) + (5 - std::abs(5 - z))); + m_WeightSum += m_Weight[z][x]; + } + } +} + + + + + +void cBiomalNoise3DComposable::Initialize(cIniFile & a_IniFile) +{ + // Params: + // The defaults generate extreme hills terrain + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DSeaLevel", 62); + m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyX", 40); + m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyY", 40); + m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyZ", 40); + m_BaseFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyX", 40); + m_BaseFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyZ", 40); + m_ChoiceFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyX", 40); + m_ChoiceFrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyY", 80); + m_ChoiceFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyZ", 40); + m_AirThreshold = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DAirThreshold", 0); + int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumChoiceOctaves", 4); + int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumDensityOctaves", 6); + int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumBaseOctaves", 6); + NOISE_DATATYPE BaseNoiseAmplitude = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseAmplitude", 1); + + // Add octaves for the choice noise: + NOISE_DATATYPE wavlen = 1, ampl = 0.5; + for (int i = 0; i < NumChoiceOctaves; i++) + { + m_ChoiceNoise.AddOctave(wavlen, ampl); + wavlen = wavlen * 2; + ampl = ampl / 2; + } + + // Add octaves for the density noises: + wavlen = 1, ampl = 1; + for (int i = 0; i < NumDensityOctaves; i++) + { + m_DensityNoiseA.AddOctave(wavlen, ampl); + m_DensityNoiseB.AddOctave(wavlen, ampl); + wavlen = wavlen * 2; + ampl = ampl / 2; + } + + // Add octaves for the base noise: + wavlen = 1, ampl = BaseNoiseAmplitude; + for (int i = 0; i < NumBaseOctaves; i++) + { + m_BaseNoise.AddOctave(wavlen, ampl); + wavlen = wavlen * 2; + ampl = ampl / 2; + } +} + + + + + +void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) +{ + if ((a_ChunkX == m_LastChunkX) && (a_ChunkZ == m_LastChunkZ)) + { + // The noise for this chunk is already generated in m_NoiseArray + return; + } + m_LastChunkX = a_ChunkX; + m_LastChunkZ = a_ChunkZ; + + // Calculate the parameters for the biomes: + ChunkParam MidPoint; + ChunkParam HeightAmp; + CalcBiomeParamArrays(a_ChunkX, a_ChunkZ, HeightAmp, MidPoint); + + // Generate all the noises: + NOISE_DATATYPE ChoiceNoise[5 * 5 * 33]; + NOISE_DATATYPE Workspace[5 * 5 * 33]; + NOISE_DATATYPE DensityNoiseA[5 * 5 * 33]; + NOISE_DATATYPE DensityNoiseB[5 * 5 * 33]; + NOISE_DATATYPE BaseNoise[5 * 5]; + NOISE_DATATYPE BlockX = static_cast(a_ChunkX * cChunkDef::Width); + NOISE_DATATYPE BlockZ = static_cast(a_ChunkZ * cChunkDef::Width); + // Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z": + m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace); + m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); + + // Calculate the final noise based on the partial noises: + for (int y = 0; y < 33; y++) + { + NOISE_DATATYPE BlockHeight = static_cast(y * 8); + for (int z = 0; z < 5; z++) + { + for (int x = 0; x < 5; x++) + { + NOISE_DATATYPE AddHeight = (BlockHeight - MidPoint[x + 5 * z]) * HeightAmp[x + 5 * z]; + + // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: + if (AddHeight < 0) + { + AddHeight *= 4; + } + + int idx = x + 5 * z + 5 * 5 * y; + Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z]; + } + } + } + LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); +} + + + + + +void cBiomalNoise3DComposable::CalcBiomeParamArrays(int a_ChunkX, int a_ChunkZ, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint) +{ + // Generate the 3*3 chunks of biomes around this chunk: + cChunkDef::BiomeMap neighborBiomes[3 * 3]; + for (int z = 0; z < 3; z++) + { + for (int x = 0; x < 3; x++) + { + m_BiomeGen->GenBiomes(a_ChunkX + x - 1, a_ChunkZ + z - 1, neighborBiomes[x + 3 * z]); + } + } + + // Sum up the biome values: + for (int z = 0; z < 5; z++) + { + for (int x = 0; x < 5; x++) + { + NOISE_DATATYPE totalHeightAmp = 0; + NOISE_DATATYPE totalMidPoint = 0; + // Add up the biomes around this point: + for (int relz = 0; relz <= AVERAGING_SIZE * 2; ++relz) + { + int colz = 16 + z * 4 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start + int neicellz = colz / 16; // Chunk Z coord relative to the neighborBiomes start + int neirelz = colz % 16; // Biome Z coord relative to cz in neighborBiomes + for (int relx = 0; relx <= AVERAGING_SIZE * 2; ++relx) + { + int colx = 16 + x * 4 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start + int neicellx = colx / 16; // Chunk X coord relative to the neighborBiomes start + int neirelx = colx % 16; // Biome X coord relative to cz in neighborBiomes + EMCSBiome biome = cChunkDef::GetBiome(neighborBiomes[neicellx + neicellz * 3], neirelx, neirelz); + NOISE_DATATYPE heightAmp, midPoint; + GetBiomeParams(biome, heightAmp, midPoint); + totalHeightAmp += heightAmp * m_Weight[relz][relx]; + totalMidPoint += midPoint * m_Weight[relz][relx]; + } // for relx + } // for relz + a_HeightAmp[x + 5 * z] = totalHeightAmp / m_WeightSum; + a_MidPoint[x + 5 * z] = totalMidPoint / m_WeightSum; + } // for x + } // for z +} + + + + + +void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint) +{ + switch (a_Biome) + { + case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; // Needs verification + case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification + case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; + case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; + + default: + { + // Make a crazy terrain so that it stands out + a_HeightAmp = 0.001f; + a_MidPoint = 90; + break; + } + } +} + + + + + +void cBiomalNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) { GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); @@ -555,7 +801,7 @@ void cNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::Hei -void cNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cBiomalNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) { GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 207aeab97..ba541fbcc 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -138,3 +138,89 @@ protected: + +class cBiomalNoise3DComposable : + public cTerrainHeightGen, + public cTerrainCompositionGen +{ +public: + cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_BiomeGen); + + void Initialize(cIniFile & a_IniFile); + +protected: + /** Number of columns around the pixel to query for biomes for averaging. */ + static const int AVERAGING_SIZE = 5; + + /** Type used for a single parameter across the entire (downscaled) chunk. */ + typedef NOISE_DATATYPE ChunkParam[5 * 5]; + + + /** The noise that is used to choose between density noise A and B. */ + cPerlinNoise m_ChoiceNoise; + + /** Density 3D noise, variant A. */ + cPerlinNoise m_DensityNoiseA; + + /** Density 3D noise, variant B. */ + cPerlinNoise m_DensityNoiseB; + + /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ + cPerlinNoise m_BaseNoise; + + /** The underlying biome generator. */ + cBiomeGenPtr m_BiomeGen; + + /** Block height of the sealevel, used for composing the terrain. */ + int m_SeaLevel; + + // Frequency of the 3D noise's first octave: + NOISE_DATATYPE m_FrequencyX; + NOISE_DATATYPE m_FrequencyY; + NOISE_DATATYPE m_FrequencyZ; + + // Frequency of the base terrain noise: + NOISE_DATATYPE m_BaseFrequencyX; + NOISE_DATATYPE m_BaseFrequencyZ; + + // Frequency of the choice noise: + NOISE_DATATYPE m_ChoiceFrequencyX; + NOISE_DATATYPE m_ChoiceFrequencyY; + NOISE_DATATYPE m_ChoiceFrequencyZ; + + // 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 + + /** Weights for summing up neighboring biomes. */ + NOISE_DATATYPE m_Weight[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1]; + + /** 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); + + /** Calculates the biome-related parameters for the chunk. */ + void CalcBiomeParamArrays(int a_ChunkX, int a_ChunkZ, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint); + + /** Returns the parameters for the specified biome. */ + void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint); + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } + + // cTerrainCompositionGen overrides: + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } +} ; + + + + -- cgit v1.2.3 From 9a50a1fe0cc641a4ec931d733702b775292a6ab6 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 10 Nov 2014 21:55:13 +0100 Subject: TallGrassGenerator: Fixed crash when too high --- src/Generating/FinishGen.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 18f8ee2bc..b8afac09a 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -199,6 +199,11 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc) // Get the top block + 1. This is the place where the grass would finaly be placed: int y = a_ChunkDesc.GetHeight(x, z) + 1; + + if (y >= 255) + { + continue; + } // Check if long grass can be placed: if ( -- cgit v1.2.3 From b525eee8e001676d54cf43cb6c74794a60038a5c Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 10 Nov 2014 22:08:07 +0100 Subject: BiomalNoise3D: Added a few biomes. --- src/Generating/Noise3DGenerator.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 3f50ea0e9..4e45aa18b 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -756,11 +756,14 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE { switch (a_Biome) { - case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; // Needs verification - case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; - case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification - case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; - case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; + case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; // Needs verification + case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; + case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; + case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification + case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; + case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; + case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; default: { -- cgit v1.2.3 From 5fb2526e0739fa27d925a686669f2c3aef56e825 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 12 Nov 2014 21:24:26 +0100 Subject: Generator: Shape initial refactoring. The code compiles, but several structure generators are broken, crash on start. --- src/Generating/CMakeLists.txt | 3 + src/Generating/ChunkDesc.cpp | 63 +++ src/Generating/ChunkDesc.h | 25 +- src/Generating/CompoGen.cpp | 332 +------------ src/Generating/CompoGen.h | 44 +- src/Generating/CompoGenBiomal.cpp | 799 ++++++++++++++++++++++++++++++++ src/Generating/CompoGenBiomal.h | 21 + src/Generating/ComposableGenerator.cpp | 99 ++-- src/Generating/ComposableGenerator.h | 95 ++-- src/Generating/DistortedHeightmap.cpp | 565 +--------------------- src/Generating/DistortedHeightmap.h | 60 +-- src/Generating/DungeonRoomsFinisher.cpp | 8 +- src/Generating/DungeonRoomsFinisher.h | 8 +- src/Generating/EndGen.cpp | 44 +- src/Generating/EndGen.h | 8 +- src/Generating/HeiGen.cpp | 47 +- src/Generating/HeiGen.h | 53 +-- src/Generating/Noise3DGenerator.cpp | 197 ++------ src/Generating/Noise3DGenerator.h | 26 +- src/Generating/ShapeGen.cpp | 140 ++++++ src/Generating/StructGen.cpp | 26 +- src/Generating/StructGen.h | 33 +- src/Generating/VillageGen.cpp | 6 +- 23 files changed, 1356 insertions(+), 1346 deletions(-) create mode 100644 src/Generating/CompoGenBiomal.cpp create mode 100644 src/Generating/CompoGenBiomal.h create mode 100644 src/Generating/ShapeGen.cpp (limited to 'src/Generating') diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index 1a26bd0d5..047452bbb 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -10,6 +10,7 @@ SET (SRCS ChunkDesc.cpp ChunkGenerator.cpp CompoGen.cpp + CompoGenBiomal.cpp ComposableGenerator.cpp DistortedHeightmap.cpp DungeonRoomsFinisher.cpp @@ -39,6 +40,7 @@ SET (HDRS ChunkDesc.h ChunkGenerator.h CompoGen.h + CompoGenBiomal.h ComposableGenerator.h DistortedHeightmap.h DungeonRoomsFinisher.h @@ -58,6 +60,7 @@ SET (HDRS RainbowRoadsGen.h Ravines.h RoughRavines.h + ShapeGen.cpp StructGen.h TestRailsGen.h Trees.h diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index 020d3bd0f..3fe81c7e4 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -152,6 +152,52 @@ int cChunkDesc::GetHeight(int a_RelX, int a_RelZ) +void cChunkDesc::SetHeightFromShape(const Shape & a_Shape) +{ + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + for (int y = cChunkDef::Height - 1; y > 0; y--) + { + if (a_Shape[y + x * 256 + z * 16 * 256] != 0) + { + cChunkDef::SetHeight(m_HeightMap, x, z, y); + break; + } + } // for y + } // for x + } // for z +} + + + + + +void cChunkDesc::GetShapeFromHeight(Shape & a_Shape) const +{ + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + int height = cChunkDef::GetHeight(m_HeightMap, x, z); + for (int y = 0; y <= height; y++) + { + 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; + } // for y + } // for x + } // for z +} + + + + + void cChunkDesc::SetUseDefaultBiomes(bool a_bUseDefaultBiomes) { m_bUseDefaultBiomes = a_bUseDefaultBiomes; @@ -366,6 +412,23 @@ HEIGHTTYPE cChunkDesc::GetMaxHeight(void) const +HEIGHTTYPE cChunkDesc::GetMinHeight(void) const +{ + HEIGHTTYPE MinHeight = m_HeightMap[0]; + for (size_t i = 1; i < ARRAYCOUNT(m_HeightMap); i++) + { + if (m_HeightMap[i] < MinHeight) + { + MinHeight = m_HeightMap[i]; + } + } + return MinHeight; +} + + + + + void cChunkDesc::FillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index 570132790..b86041a7d 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -29,10 +29,17 @@ class cChunkDesc { public: // tolua_end + + /** The datatype used to represent the entire chunk worth of shape. + 0 = air + 1 = solid + Indexed as [y + 256 * z + 256 * 16 * x]. */ + 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(); @@ -57,10 +64,21 @@ public: EMCSBiome GetBiome(int a_RelX, int a_RelZ); // These operate on the heightmap, so they could get out of sync with the data - // Use UpdateHeightmap() to re-sync + // Use UpdateHeightmap() to re-calculate heightmap from the block data void SetHeight(int a_RelX, int a_RelZ, int a_Height); int GetHeight(int a_RelX, int a_RelZ); + // tolua_end + + /** Sets the heightmap to match the given shape data. + Note that this ignores overhangs; the method is mostly used by old composition generators. */ + void SetHeightFromShape(const Shape & a_Shape); + + /** Sets the shape in a_Shape to match the heightmap stored currently in m_HeightMap. */ + void GetShapeFromHeight(Shape & a_Shape) const; + + // tolua_begin + // Default generation: void SetUseDefaultBiomes(bool a_bUseDefaultBiomes); bool IsUsingDefaultBiomes(void) const; @@ -77,8 +95,11 @@ public: /** Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas */ void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ); - /** Returns the maximum height value in the heightmap */ + /** Returns the maximum height value in the heightmap. */ HEIGHTTYPE GetMaxHeight(void) const; + + /** 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( diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 29b831dfd..ef13b7c6b 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -21,8 +21,9 @@ //////////////////////////////////////////////////////////////////////////////// // cCompoGenSameBlock: -void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { + a_ChunkDesc.SetHeightFromShape(a_Shape); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { @@ -63,7 +64,7 @@ void cCompoGenSameBlock::InitializeCompoGen(cIniFile & a_IniFile) //////////////////////////////////////////////////////////////////////////////// // cCompoGenDebugBiomes: -void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { static BLOCKTYPE Blocks[] = { @@ -92,6 +93,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc) E_BLOCK_BEDROCK, } ; + a_ChunkDesc.SetHeightFromShape(a_Shape); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) @@ -131,7 +133,7 @@ cCompoGenClassic::cCompoGenClassic(void) : -void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { /* The classic composition means: - 1 layer of grass, 3 of dirt and the rest stone, if the height > sealevel + beachheight @@ -142,6 +144,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc) */ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); + a_ChunkDesc.SetHeightFromShape(a_Shape); // The patterns to use for different situations, must be same length! const BLOCKTYPE PatternGround[] = {m_BlockTop, m_BlockMiddle, m_BlockMiddle, m_BlockMiddle} ; @@ -209,323 +212,6 @@ void cCompoGenClassic::InitializeCompoGen(cIniFile & a_IniFile) -//////////////////////////////////////////////////////////////////////////////// -// cCompoGenBiomal: - -void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - - int ChunkX = a_ChunkDesc.GetChunkX(); - int ChunkZ = a_ChunkDesc.GetChunkZ(); - - /* - _X 2013_04_22: - There's no point in generating the whole cubic noise at once, because the noise values are used in - only about 20 % of the cases, so the speed gained by precalculating is lost by precalculating too much data - */ - - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - int Height = a_ChunkDesc.GetHeight(x, z); - if (Height > m_SeaLevel) - { - 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: - { - 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()); - break; - } - case biMushroomIsland: - case biMushroomShore: - { - FillColumnMycelium(x, z, Height, a_ChunkDesc.GetBlockTypes()); - break; - } - default: - { - // TODO - ASSERT(!"CompoGenBiomal: Biome not implemented yet!"); - break; - } - } - } - else - { - switch (a_ChunkDesc.GetBiome(x, z)) - { - case biDesert: - case biBeach: - { - // Fill with water, sand, sandstone and stone - FillColumnWaterSand(x, z, Height, a_ChunkDesc.GetBlockTypes()); - break; - } - default: - { - // Fill with water, sand/dirt/clay mix and stone - if (m_Noise.CubicNoise2D(0.3f * (cChunkDef::Width * ChunkX + x), 0.3f * (cChunkDef::Width * ChunkZ + z)) < 0) - { - FillColumnWaterSand(x, z, Height, a_ChunkDesc.GetBlockTypes()); - } - else - { - FillColumnWaterDirt(x, z, Height, a_ChunkDesc.GetBlockTypes()); - } - break; - } - } // switch (biome) - a_ChunkDesc.SetHeight(x, z, m_SeaLevel + 1); - } // else (under water) - a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); - } // for x - } // for z -} - - - - - -void cCompoGenBiomal::InitializeCompoGen(cIniFile & a_IniFile) -{ - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "BiomalSeaLevel", m_SeaLevel) - 1; -} - - - - - -void cCompoGenBiomal::FillColumnGrass(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - BLOCKTYPE Pattern[] = - { - E_BLOCK_GRASS, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - } ; - 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::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[] = - { - E_BLOCK_SAND, - E_BLOCK_SAND, - E_BLOCK_SAND, - E_BLOCK_SANDSTONE, - } ; - 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::FillColumnMycelium (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - BLOCKTYPE Pattern[] = - { - E_BLOCK_MYCELIUM, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - } ; - 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::FillColumnWaterSand(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - FillColumnSand(a_RelX, a_RelZ, a_Height, a_BlockTypes); - for (int y = a_Height + 1; y <= m_SeaLevel + 1; y++) - { - cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); - } -} - - - - - -void cCompoGenBiomal::FillColumnWaterDirt(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - // Dirt - BLOCKTYPE Pattern[] = - { - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - } ; - 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); - } - for (int y = a_Height + 1; y <= m_SeaLevel + 1; y++) - { - cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); - } -} - - - - - - -void cCompoGenBiomal::FillColumnPattern(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes, const BLOCKTYPE * a_Pattern, int a_PatternSize) -{ - for (int y = a_Height, idx = 0; (y >= 0) && (idx < a_PatternSize); y--, idx++) - { - cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, a_Pattern[idx]); - } -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cCompoGenNether: @@ -540,7 +226,7 @@ cCompoGenNether::cCompoGenNether(int a_Seed) : -void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); @@ -696,7 +382,7 @@ cCompoGenCache::~cCompoGenCache() -void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { #ifdef _DEBUG if (((m_NumHits + m_NumMisses) % 1024) == 10) @@ -739,7 +425,7 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc) // Not in the cache: m_NumMisses++; - m_Underlying->ComposeTerrain(a_ChunkDesc); + m_Underlying->ComposeTerrain(a_ChunkDesc, a_Shape); // Insert it as the first item in the MRU order: int Idx = m_CacheOrder[m_CacheSize - 1]; diff --git a/src/Generating/CompoGen.h b/src/Generating/CompoGen.h index b145b6ba3..16c00c13d 100644 --- a/src/Generating/CompoGen.h +++ b/src/Generating/CompoGen.h @@ -38,7 +38,7 @@ protected: bool m_IsBedrocked; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; @@ -55,7 +55,7 @@ public: protected: // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; } ; @@ -81,7 +81,7 @@ protected: BLOCKTYPE m_BlockSea; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; @@ -89,40 +89,6 @@ protected: -class cCompoGenBiomal : - public cTerrainCompositionGen -{ -public: - cCompoGenBiomal(int a_Seed) : - m_Noise(a_Seed + 1000), - m_SeaLevel(62) - { - } - -protected: - - cNoise m_Noise; - int m_SeaLevel; - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - 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); - void FillColumnWaterDirt(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); - - void FillColumnPattern (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes, const BLOCKTYPE * a_Pattern, int a_PatternSize); -} ; - - - - - class cCompoGenNether : public cTerrainCompositionGen { @@ -136,7 +102,7 @@ protected: int m_Threshold; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; @@ -153,7 +119,7 @@ public: ~cCompoGenCache(); // cTerrainCompositionGen override: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; protected: diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp new file mode 100644 index 000000000..1e3363606 --- /dev/null +++ b/src/Generating/CompoGenBiomal.cpp @@ -0,0 +1,799 @@ + +// CompoGenBiomal.cpp + +// Implements the cCompoGenBiomal class representing the biome-aware composition generator + +#include "Globals.h" +#include "ComposableGenerator.h" +#include "../IniFile.h" +#include "../Noise.h" +#include "../LinearUpscale.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// 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 columns. */ +class cPattern +{ +public: + struct BlockInfo + { + BLOCKTYPE m_BlockType; + NIBBLETYPE m_BlockMeta; + }; + + cPattern(BlockInfo * 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 BlockInfo Stone = {E_BLOCK_STONE, 0}; + for (size_t i = a_Count; i < cChunkDef::Height; i++) + { + m_Pattern[i] = Stone; + } + } + + const BlockInfo * Get(void) const { return m_Pattern; } + +protected: + BlockInfo m_Pattern[cChunkDef::Height]; +} ; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// The arrays to use for the top block pattern definitions: + +static cPattern::BlockInfo 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 cPattern::BlockInfo tbSand[] = +{ + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SANDSTONE, 0}, +} ; + +static cPattern::BlockInfo 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 cPattern::BlockInfo 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 cPattern::BlockInfo 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 cPattern::BlockInfo tbMycelium[] = +{ + {E_BLOCK_MYCELIUM, 0}, + {E_BLOCK_DIRT, 0}, + {E_BLOCK_DIRT, 0}, + {E_BLOCK_DIRT, 0}, +} ; + +static cPattern::BlockInfo tbGravel[] = +{ + {E_BLOCK_GRAVEL, 0}, + {E_BLOCK_GRAVEL, 0}, + {E_BLOCK_GRAVEL, 0}, + {E_BLOCK_STONE, 0}, +} ; + +static cPattern::BlockInfo tbStone[] = +{ + {E_BLOCK_STONE, 0}, + {E_BLOCK_STONE, 0}, + {E_BLOCK_STONE, 0}, + {E_BLOCK_STONE, 0}, +} ; + + + +//////////////////////////////////////////////////////////////////////////////// +// Ocean floor pattern top-block definitions: + +static cPattern::BlockInfo tbOFSand[] = +{ + {E_BLOCK_SAND, 0}, + {E_BLOCK_SAND, 0}, + {E_BLOCK_SAND, 0}, + {E_BLOCK_SANDSTONE, 0} +} ; + +static cPattern::BlockInfo tbOFClay[] = +{ + { E_BLOCK_CLAY, 0}, + { E_BLOCK_CLAY, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, +} ; + +static cPattern::BlockInfo tbOFOrangeClay[] = +{ + { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, +} ; + + + + + + +//////////////////////////////////////////////////////////////////////////////// +// 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 patGravel (tbGravel, ARRAYCOUNT(tbGravel)); +static cPattern patStone (tbStone, ARRAYCOUNT(tbStone)); + +static cPattern patOFSand (tbOFSand, ARRAYCOUNT(tbOFSand)); +static cPattern patOFClay (tbOFClay, ARRAYCOUNT(tbOFClay)); +static cPattern patOFOrangeClay(tbOFOrangeClay, ARRAYCOUNT(tbOFOrangeClay)); + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cCompoGenBiomal: + +class cCompoGenBiomal : + public cTerrainCompositionGen +{ +public: + cCompoGenBiomal(int a_Seed) : + m_SeaLevel(62), + m_OceanFloorSelect(a_Seed + 1), + m_MesaFloor(a_Seed + 2) + { + initMesaPattern(a_Seed); + } + +protected: + /** The block height at which water is generated instead of air. */ + int 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; + + /** Noise used for the floor of the clay blocks in mesa biomes. */ + cNoise m_MesaFloor; + + + // cTerrainCompositionGen overrides: + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override + { + a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + ComposeColumn(a_ChunkDesc, x, z, &(a_Shape[x * 256 + z * 16 * 256])); + } // for x + } // for z + } + + + + virtual void InitializeCompoGen(cIniFile & a_IniFile) override + { + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel) - 1; + } + + + + /** Initializes the m_MesaPattern with a pattern based on the generator's seed. */ + void initMesaPattern(int a_Seed) + { + // In a loop, choose whether to use one, two or three 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 = ARRAYCOUNT(m_MesaPattern) - 1; + while (idx >= 0) + { + // A layer group of 1 - 2 color stained clay: + int rnd = patternNoise.IntNoise1DInt(idx) / 7; + int numLayers = (rnd % 2) + 1; + rnd /= 2; + for (int lay = 0; lay < numLayers; lay++) + { + int numBlocks = layerSizes[(rnd % ARRAYCOUNT(layerSizes))]; + NIBBLETYPE Color = allowedColors[(rnd / 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 + rnd /= 32; + for (int block = 0; block < numBlocks; block++, idx--) + { + m_MesaPattern[idx].m_BlockMeta = Color; + m_MesaPattern[idx].m_BlockType = E_BLOCK_STAINED_CLAY; + } // for block + } // for lay + + // A layer of hardened clay in between the layer group: + int numBlocks = (rnd % 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].m_BlockMeta = 0; + m_MesaPattern[idx].m_BlockType = E_BLOCK_HARDENED_CLAY; + } // for block + } // while (idx >= 0) + } + + + + /** 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, const Byte * a_ShapeColumn) + { + // 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 biForest: + case biTaiga: + case biSwampland: + case biRiver: + case biFrozenOcean: + case biFrozenRiver: + case biIcePlains: + case biIceMountains: + case biForestHills: + case biTaigaHills: + case biExtremeHillsEdge: + case biExtremeHillsPlus: + case biExtremeHills: + case biJungle: + case biJungleHills: + case biJungleEdge: + case biDeepOcean: + case biStoneBeach: + case biColdBeach: + case biBirchForest: + case biBirchForestHills: + case biRoofedForest: + case biColdTaiga: + case biColdTaigaHills: + case biSavanna: + case biSavannaPlateau: + case biSunflowerPlains: + case biFlowerForest: + case biTaigaM: + case biSwamplandM: + case biIcePlainsSpikes: + case biJungleM: + case biJungleEdgeM: + case biBirchForestM: + case biBirchForestHillsM: + case biRoofedForestM: + case biColdTaigaM: + case biSavannaM: + case biSavannaPlateauM: + { + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patGrass.Get(), a_ShapeColumn); + return; + } + + case biMegaTaiga: + case biMegaTaigaHills: + case biMegaSpruceTaiga: + case biMegaSpruceTaigaHills: + { + // Select the pattern to use - podzol, grass or grassless dirt: + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; + NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); + const cPattern::BlockInfo * Pattern = (Val < -0.9) ? patGrassLess.Get() : ((Val > 0) ? patPodzol.Get() : patGrass.Get()); + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); + return; + } + + case biDesertHills: + case biDesert: + case biDesertM: + case biBeach: + { + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patSand.Get(), a_ShapeColumn); + return; + } + + case biMushroomIsland: + case biMushroomShore: + { + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patMycelium.Get(), a_ShapeColumn); + 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, a_ShapeColumn); + return; + } + + case biExtremeHillsPlusM: + case biExtremeHillsM: + { + // Select the pattern to use - gravel, stone or grass: + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; + NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); + const cPattern::BlockInfo * Pattern = (Val < 0.0) ? patStone.Get() : patGrass.Get(); + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); + return; + } + default: + { + ASSERT(!"Unhandled biome"); + return; + } + } // switch (Biome) + } + + + + /** 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 cPattern::BlockInfo * a_Pattern, const Byte * a_ShapeColumn) + { + bool HasHadWater = false; + int PatternIdx = 0; + for (int y = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); y > 0; y--) + { + if (a_ShapeColumn[y] > 0) + { + // "ground" part, use the pattern: + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[PatternIdx].m_BlockType, a_Pattern[PatternIdx].m_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: + if (a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean) + { + a_Pattern = patGravel.Get(); + } + else + { + a_Pattern = ChooseOceanFloorPattern(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); + } + HasHadWater = true; + } // for y + a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); + } + + + + /** Fills the specified column with mesa pattern, based on the column height */ + void FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const Byte * a_ShapeColumn) + { + // 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 with red sand floor: + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patOFOrangeClay.Get(), a_ShapeColumn); + return; + } + + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * 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 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; + bool HasHadWater = false; + for (int y = Top; y > 0; y--) + { + if (a_ShapeColumn[y] > 0) + { + // "ground" part, use the pattern: + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, Pattern[PatternIdx].m_BlockType, Pattern[PatternIdx].m_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_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); + HasHadWater = true; + } // for y + a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); + } + + + + /** 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) + { + // 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)(a_ChunkX * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkZ * 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(); + } + } + + + + #if 0 + /** Fills a single column with grass-based terrain (grass or water, dirt, stone). */ + void FillColumnGrass(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) + { + static const PatternItem pattern[] = + { + { E_BLOCK_GRASS, 0}, + { E_BLOCK_DIRT, 0}, + { E_BLOCK_DIRT, 0}, + { E_BLOCK_DIRT, 0}, + } ; + FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); + } + + + + /** Fills a single column with grass-based terrain (grass or water, dirt, stone). */ + void FillColumnStone(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) + { + static const PatternItem pattern[] = + { + { E_BLOCK_STONE, 0}, + } ; + FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); + } + + + + /** Fills a single column with Mesa-like terrain (variations of clay). */ + void FillColumnMesa(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) + { + // Fill with grass and dirt on the very top of mesa plateaus: + size_t curIdx = 0; + for (int y = 255; y > m_MesaDirtLevel; y--) + { + if (a_ShapeColumn[y] > 0) + { + a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, (curIdx > 0) ? E_BLOCK_DIRT : E_BLOCK_GRASS); + curIdx += 1; + } + else + { + curIdx = 0; + } + } // for y + + // Fill with clays from the DirtLevel down to SandLevel: + for (int y = m_MesaDirtLevel; y > m_MesaSandLevel; y--) + { + if (a_ShapeColumn[y] > 0) + { + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, m_MesaPattern[y].m_BlockType, m_MesaPattern[y].m_BlockMeta); + } + else + { + curIdx = 0; + } + } // for y + + // If currently air, switch to red sand pattern: + static const PatternItem redSandPattern[] = + { + { E_BLOCK_SAND, E_META_SAND_RED}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE}, + }; + Pattern pattern; + size_t patternSize; + if (curIdx == 0) + { + pattern = redSandPattern; + patternSize = ARRAYCOUNT(redSandPattern); + } + else + { + pattern = m_MesaPattern + m_MesaSandLevel; + patternSize = static_cast(m_MesaSandLevel); + } + + // Fill with current pattern (MesaPattern or RedSand) until sealevel: + for (int y = m_MesaSandLevel; y > m_SeaLevel; y--) + { + if (a_ShapeColumn[y] > 0) + { + if (curIdx >= patternSize) + { + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE); + } + else + { + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, pattern[curIdx].m_BlockType, pattern[curIdx].m_BlockMeta); + } + curIdx += 1; + } + else + { + // Air resets the pattern to red sand: + curIdx = 0; + pattern = redSandPattern; + patternSize = ARRAYCOUNT(redSandPattern); + } + } // for y + + // If there is an ocean, fill it with water and then redsand: + int y = m_SeaLevel; + for (; y > 0; y--) + { + if ((a_ShapeColumn[y] == 0) || (curIdx >= ARRAYCOUNT(redSandPattern))) + { + // water pocket or out of red sand pattern, use stone from now on + break; + } + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE); + curIdx = curIdx + 1; + } // for y + + // The rest should be filled with stone: + for (; y > 0; y--) + { + if (a_ShapeColumn[y] > 0) + { + a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); + } + } // for y + } + + + + /** Fills a single column with megataiga-based terrain (grass or podzol on top). */ + void FillColumnMegaTaiga(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) + { + // TODO + } + + + + /** Fills a single column with sand-based terrain (such as desert or beach). */ + void FillColumnSand(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) + { + static const PatternItem pattern[] = + { + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SANDSTONE, 0}, + } ; + FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); + } + + + + void FillColumnMycelium(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) + { + static const PatternItem pattern[] = + { + { E_BLOCK_MYCELIUM, 0}, + { E_BLOCK_DIRT, 0}, + { E_BLOCK_DIRT, 0}, + { E_BLOCK_DIRT, 0}, + } ; + FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); + } + + + + /** Fills the column with the specified pattern, repeating it if there's an air pocket in between. */ + void FillColumnPattern(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc, Pattern a_Pattern, size_t a_PatternSize) + { + // Fill with pattern until sealevel: + size_t curIdx = 0; + for (int y = 255; y > m_SeaLevel; y--) + { + if (a_ShapeColumn[y] > 0) + { + // Continue with the pattern: + if (curIdx >= a_PatternSize) + { + a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); + } + else + { + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[curIdx].m_BlockType, a_Pattern[curIdx].m_BlockMeta); + } + curIdx += 1; + } + else + { + // Air pocket, restart the pattern: + curIdx = 0; + } + } // for y + + // From sealevel downward use the ocean floor pattern: + FillOceanFloor(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, a_Pattern, a_PatternSize, curIdx); + } + + + /** Fills the blocks from sealevel down to bottom with ocean-floor pattern. + a_PatternStartOffset specifies the offset at which to start the pattern, in case there was air just above. */ + void FillOceanFloor(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc, Pattern a_Pattern, size_t a_PatternSize, size_t a_PatternStartOffset) + { + for (int y = m_SeaLevel; y > 0; y--) + { + if (a_ShapeColumn[y] > 0) + { + // TODO + } + } // for y + } + #endif +} ; + + + + + +cTerrainCompositionGenPtr CreateCompoGenBiomal(int a_Seed) +{ + return std::make_shared(a_Seed); +} + + + diff --git a/src/Generating/CompoGenBiomal.h b/src/Generating/CompoGenBiomal.h new file mode 100644 index 000000000..a3a65d3dc --- /dev/null +++ b/src/Generating/CompoGenBiomal.h @@ -0,0 +1,21 @@ + +// CompoGenBiomal.h + + + + + +#pragma once + +#include "ComposableGenerator.h" + + + + + +/** Returns a new instance of the Biomal composition generator. */ +cTerrainCompositionGenPtr CreateCompoGenBiomal(int a_Seed); + + + + diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 5f46574c7..5420e12ac 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -17,6 +17,8 @@ #include "StructGen.h" #include "FinishGen.h" +#include "CompoGenBiomal.h" + #include "Caves.h" #include "DistortedHeightmap.h" #include "DungeonRoomsFinisher.h" @@ -39,7 +41,7 @@ //////////////////////////////////////////////////////////////////////////////// // cTerrainCompositionGen: -cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed) +cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, int a_Seed) { AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", ""); if (CompoGenName.empty()) @@ -48,63 +50,52 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile CompoGenName = "Biomal"; } - cTerrainCompositionGen * res = nullptr; - if (NoCaseCompare(CompoGenName, "sameblock") == 0) + // Compositor list is alpha-sorted + cTerrainCompositionGenPtr res; + if (NoCaseCompare(CompoGenName, "Biomal") == 0) { - res = new cCompoGenSameBlock; + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0) + else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) { - res = new cCompoGenDebugBiomes; + // The composition that used to be provided with BiomalNoise3D is now provided by the Biomal compositor: + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "classic") == 0) + else if (NoCaseCompare(CompoGenName, "Classic") == 0) { - res = new cCompoGenClassic; + res = std::make_shared(); } - else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) + else if (NoCaseCompare(CompoGenName, "DebugBiomes") == 0) { - res = new cDistortedHeightmap(a_Seed, a_BiomeGen); + res = std::make_shared(); } - else if (NoCaseCompare(CompoGenName, "end") == 0) + else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) { - res = new cEndGen(a_Seed); + // The composition that used to be provided with DistortedHeightmap is now provided by the Biomal compositor: + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "nether") == 0) + else if (NoCaseCompare(CompoGenName, "End") == 0) { - res = new cCompoGenNether(a_Seed); + res = std::make_shared(a_Seed); } - else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) + else if (NoCaseCompare(CompoGenName, "Nether") == 0) { - res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen); + res = std::make_shared(a_Seed); } else if (NoCaseCompare(CompoGenName, "Noise3D") == 0) { - res = new cNoise3DComposable(a_Seed); + // The composition that used to be provided with Noise3D is now provided by the Biomal compositor: + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "biomal") == 0) + else if (NoCaseCompare(CompoGenName, "SameBlock") == 0) { - res = new cCompoGenBiomal(a_Seed); - - /* - // Performance-testing: - LOGINFO("Measuring performance of cCompoGenBiomal..."); - clock_t BeginTick = clock(); - for (int x = 0; x < 500; x++) - { - cChunkDesc Desc(200 + x * 8, 200 + x * 8); - a_BiomeGen->GenBiomes(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetBiomeMap()); - a_HeightGen->GenHeightMap(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetHeightMap()); - res->ComposeTerrain(Desc); - } - clock_t Duration = clock() - BeginTick; - LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); - //*/ + res = std::make_shared(); } else { LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); - return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed); + return CreateCompositionGen(a_IniFile, a_BiomeGen, a_ShapeGen, a_Seed); } ASSERT(res != nullptr); @@ -124,7 +115,7 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) : super(a_ChunkGenerator), m_BiomeGen(), - m_HeightGen(), + m_ShapeGen(), m_CompositionGen() { } @@ -138,7 +129,7 @@ void cComposableGenerator::Initialize(cIniFile & a_IniFile) super::Initialize(a_IniFile); InitBiomeGen(a_IniFile); - InitHeightGen(a_IniFile); + InitShapeGen(a_IniFile); InitCompositionGen(a_IniFile); InitFinishGens(a_IniFile); } @@ -166,15 +157,22 @@ 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()) { - m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetHeightMap()); + m_ShapeGen->GenShape(a_ChunkX, a_ChunkZ, shape); + a_ChunkDesc.SetHeightFromShape(shape); + } + else + { + // Convert the heightmap in a_ChunkDesc into shape: + a_ChunkDesc.GetShapeFromHeight(shape); } bool ShouldUpdateHeightmap = false; if (a_ChunkDesc.IsUsingDefaultComposition()) { - m_CompositionGen->ComposeTerrain(a_ChunkDesc); + m_CompositionGen->ComposeTerrain(a_ChunkDesc, shape); ShouldUpdateHeightmap = true; } @@ -234,13 +232,15 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile) -void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile) +void cComposableGenerator::InitShapeGen(cIniFile & a_IniFile) { bool CacheOffByDefault = false; - m_HeightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault); + m_ShapeGen = cTerrainShapeGen::CreateShapeGen(a_IniFile, m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault); + /* + // TODO // Add a cache, if requested: - int CacheSize = a_IniFile.GetValueSetI("Generator", "HeightGenCacheSize", CacheOffByDefault ? 0 : 64); + int CacheSize = a_IniFile.GetValueSetI("Generator", "ShapeGenCacheSize", CacheOffByDefault ? 0 : 64); if (CacheSize > 0) { if (CacheSize < 4) @@ -253,6 +253,7 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile) LOGD("Using a cache for Heightgen of size %d.", CacheSize); m_HeightGen = cTerrainHeightGenPtr(new cHeiGenCache(m_HeightGen, CacheSize)); } + */ } @@ -261,7 +262,7 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile) void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile) { - m_CompositionGen = cTerrainCompositionGen::CreateCompositionGen(a_IniFile, m_BiomeGen, *m_HeightGen, m_ChunkGenerator.GetSeed()); + m_CompositionGen = cTerrainCompositionGen::CreateCompositionGen(a_IniFile, m_BiomeGen, m_ShapeGen, m_ChunkGenerator.GetSeed()); int CompoGenCacheSize = a_IniFile.GetValueSetI("Generator", "CompositionGenCacheSize", 64); if (CompoGenCacheSize > 1) @@ -333,7 +334,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) int MaxSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMaxSize", 7); int MinSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMinSize", 5); AString HeightDistrib = a_IniFile.GetValueSet ("Generator", "DungeonRoomsHeightDistrib", "0, 0; 10, 10; 11, 500; 40, 500; 60, 40; 90, 1"); - m_FinishGens.push_back(cFinishGenPtr(new cDungeonRoomsFinisher(m_HeightGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib))); + m_FinishGens.push_back(cFinishGenPtr(new cDungeonRoomsFinisher(m_ShapeGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib))); } else if (NoCaseCompare(*itr, "Ice") == 0) { @@ -342,7 +343,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) else if (NoCaseCompare(*itr, "LavaLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10); - m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, m_HeightGen, Probability))); + m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, m_ShapeGen, Probability))); } else if (NoCaseCompare(*itr, "LavaSprings") == 0) { @@ -580,7 +581,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "Trees") == 0) { - m_FinishGens.push_back(cFinishGenPtr(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen))); + m_FinishGens.push_back(cFinishGenPtr(new cStructGenTrees(Seed, m_BiomeGen, m_ShapeGen, m_CompositionGen))); } else if (NoCaseCompare(*itr, "UnderwaterBases") == 0) { @@ -588,7 +589,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) int MaxOffset = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxOffset", 128); int MaxDepth = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxDepth", 7); int MaxSize = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxSize", 128); - m_FinishGens.push_back(cFinishGenPtr(new cUnderwaterBaseGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, m_BiomeGen))); + m_FinishGens.push_back(std::make_shared(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, m_BiomeGen)); } else if (NoCaseCompare(*itr, "Villages") == 0) { @@ -598,12 +599,12 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) int MaxSize = a_IniFile.GetValueSetI("Generator", "VillageMaxSize", 128); int MinDensity = a_IniFile.GetValueSetI("Generator", "VillageMinDensity", 50); int MaxDensity = a_IniFile.GetValueSetI("Generator", "VillageMaxDensity", 80); - m_FinishGens.push_back(cFinishGenPtr(new cVillageGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, m_BiomeGen, m_HeightGen))); + m_FinishGens.push_back(std::make_shared(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, m_BiomeGen, m_CompositedHeightCache)); } else if (NoCaseCompare(*itr, "WaterLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25); - m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, m_HeightGen, Probability))); + m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, m_ShapeGen, Probability))); } else if (NoCaseCompare(*itr, "WaterSprings") == 0) { diff --git a/src/Generating/ComposableGenerator.h b/src/Generating/ComposableGenerator.h index a091f8d53..86c30e090 100644 --- a/src/Generating/ComposableGenerator.h +++ b/src/Generating/ComposableGenerator.h @@ -26,20 +26,16 @@ See http://forum.mc-server.org/showthread.php?tid=409 for details. // Forward-declare the shared pointers to subgenerator classes: class cBiomeGen; +class cTerrainShapeGen; class cTerrainHeightGen; class cTerrainCompositionGen; class cFinishGen; typedef SharedPtr cBiomeGenPtr; +typedef SharedPtr cTerrainShapeGenPtr; typedef SharedPtr cTerrainHeightGenPtr; typedef SharedPtr cTerrainCompositionGenPtr; typedef SharedPtr cFinishGenPtr; -// fwd: Noise3DGenerator.h -class cNoise3DComposable; - -// fwd: DistortedHeightmap.h -class cDistortedHeightmap; - @@ -70,28 +66,54 @@ public: -/** The interface that a terrain height generator must implement -A terrain height generator takes chunk coords on input and outputs an array of terrain heights for that chunk. -The output array is sequenced in the same way as the BiomeGen's biome data. +/** The interface that a terrain shape generator must implement +A terrain shape generator takes chunk coords on input and outputs a 3D array of "shape" for that chunk. The shape here +represents the distinction between air and solid; there's no representation of Water since that is added by the +composition geenrator. +The output array is indexed [y + 256 * z + 16 * 256 * x], so that it's fast to later compose a single column of the terrain, +which is the dominant operation following the shape generation. The generator may request biome information from the underlying BiomeGen, it may even request information for -other chunks than the one it's currently generating (possibly neighbors - for averaging) +other chunks than the one it's currently generating (neighbors - for averaging) */ -class cTerrainHeightGen +class cTerrainShapeGen { public: - virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants + virtual ~cTerrainShapeGen() {} // Force a virtual destructor in descendants - /** Generates heightmap for the given chunk */ - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) = 0; + /** 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 InitializeHeightGen(cIniFile & a_IniFile) {} + virtual void InitializeShapeGen(cIniFile & a_IniFile) {} - /** Creates the correct TerrainHeightGen descendant based on the ini file settings and the seed provided. - a_BiomeGen is the underlying biome generator, some height generators may depend on it to generate more biomes + /** 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 - Implemented in HeiGen.cpp! + Implemented in ShapeGen.cpp! */ + static cTerrainShapeGenPtr CreateShapeGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault); +} ; + + + + + +/** The interface that is used to query terrain height from the shape generator. +Usually the structure generators require only the final heightmap, and generating the whole shape only to +consume the heightmap is wasteful, so this interface is used instead; it has a cache implemented over it so +that data is retained. */ +class cTerrainHeightGen +{ +public: + virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants + + /** Retrieves the heightmap for the specified chunk. */ + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) = 0; + + /** Initializes the generator, reading its parameters from the INI file. */ + virtual void InitializeHeightGen(cIniFile & a_IniFile) {} + + /** Creates a cTerrainHeightGen descendant based on the INI file settings. */ static cTerrainHeightGenPtr CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault); } ; @@ -109,16 +131,18 @@ class cTerrainCompositionGen public: virtual ~cTerrainCompositionGen() {} // Force a virtual destructor in descendants - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) = 0; + /** 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 to generate more biomes - a_HeightGen is the underlying height generator, some composition generators may depend on it providing additional values + 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 */ - static cTerrainCompositionGenPtr CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed); + static cTerrainCompositionGenPtr CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, int a_Seed); } ; @@ -128,7 +152,7 @@ public: /** The interface that a finisher must implement Finisher implements changes to the chunk after the rough terrain has been generated. Examples of finishers are trees, snow, ore, lilypads and others. -Note that a worldgenerator may contain multiple finishers. +Note that a worldgenerator may contain multiple finishers, chained one after another. Also note that previously we used to distinguish between a structuregen and a finisher; this distinction is no longer relevant, all structure generators are considered finishers now (#398) */ @@ -154,23 +178,34 @@ class cComposableGenerator : 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; virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override; protected: - // The generation composition: - cBiomeGenPtr m_BiomeGen; - cTerrainHeightGenPtr m_HeightGen; + // The generator's composition: + /** The biome generator. */ + cBiomeGenPtr m_BiomeGen; + + /** The terrain shape generator. */ + cTerrainShapeGenPtr m_ShapeGen; + + /** The terrain composition generator. */ cTerrainCompositionGenPtr m_CompositionGen; - cFinishGenList m_FinishGens; + + /** The cache for the heights of the composited terrain. */ + cTerrainHeightGenPtr m_CompositedHeightCache; + + /** The finisher generators, in the order in which they are applied. */ + cFinishGenList m_FinishGens; - /** Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly */ + /** Reads the BiomeGen settings from the ini and initializes m_BiomeGen accordingly */ void InitBiomeGen(cIniFile & a_IniFile); - /** Reads the HeightGen settings from the ini and initializes m_HeightGen accordingly */ - void InitHeightGen(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); diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index d5bc6ab55..e1ed9b450 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -14,163 +14,6 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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}, -} ; - -static cDistortedHeightmap::sBlockInfo tbGravel[] = -{ - {E_BLOCK_GRAVEL, 0}, - {E_BLOCK_GRAVEL, 0}, - {E_BLOCK_GRAVEL, 0}, - {E_BLOCK_STONE, 0}, -} ; - -static cDistortedHeightmap::sBlockInfo tbStone[] = -{ - {E_BLOCK_STONE, 0}, - {E_BLOCK_STONE, 0}, - {E_BLOCK_STONE, 0}, - {E_BLOCK_STONE, 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 patGravel (tbGravel, ARRAYCOUNT(tbGravel)); -static cPattern patStone (tbStone, ARRAYCOUNT(tbStone)); - -static cPattern patOFSand (tbOFSand, ARRAYCOUNT(tbOFSand)); -static cPattern patOFClay (tbOFClay, ARRAYCOUNT(tbOFClay)); -static cPattern patOFRedSand(tbOFRedSand, ARRAYCOUNT(tbOFRedSand)); - - - - - //////////////////////////////////////////////////////////////////////////////// // cDistortedHeightmap: @@ -237,7 +80,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}, // 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: + // Release 1.7 biome variants: /* biSunflowerPlains */ { 1.0f, 1.0f}, // 129 /* biDesertM */ { 1.0f, 1.0f}, // 130 /* biExtremeHillsM */ {16.0f, 16.0f}, // 131 @@ -279,8 +122,6 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGenPtr 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(new cHeiGenBiomal(a_Seed, a_BiomeGen)), m_HeightGen(m_UnderlyingHeiGen, 64), @@ -293,8 +134,6 @@ cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGenPtr 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); } @@ -309,7 +148,7 @@ void cDistortedHeightmap::Initialize(cIniFile & a_IniFile) } // Read the params from the INI file: - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "DistortedHeightmapSeaLevel", 62); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyX", 10); m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyY", 10); m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyZ", 10); @@ -321,89 +160,6 @@ 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)) @@ -474,23 +230,17 @@ void cDistortedHeightmap::GenerateHeightArray(void) -void cDistortedHeightmap::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cDistortedHeightmap::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { PrepareState(a_ChunkX, a_ChunkZ); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - int NoiseArrayIdx = x + 17 * 257 * z; - cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel - 1); - for (int y = cChunkDef::Height - 1; y > m_SeaLevel - 1; y--) + int idx = x + 17 * 257 * z; + for (int y = 0; y < cChunkDef::Height; y++) { - int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y]; - if (y < HeightMapHeight) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } + a_Shape[y + x * 256 + z * 16 * 256] = (y < m_DistortedHeightmap[idx + y * 17]) ? 1 : 0; } // for y } // for x } // for z @@ -500,36 +250,7 @@ void cDistortedHeightmap::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::He -void cDistortedHeightmap::InitializeHeightGen(cIniFile & a_IniFile) -{ - Initialize(a_IniFile); -} - - - - - -void cDistortedHeightmap::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - // Prepare the internal state for generating this chunk: - PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - // Compose: - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - ComposeColumn(a_ChunkDesc, x, z); - } // for x - } // for z -} - - - - - -void cDistortedHeightmap::InitializeCompoGen(cIniFile & a_IniFile) +void cDistortedHeightmap::InitializeShapeGen(cIniFile & a_IniFile) { Initialize(a_IniFile); } @@ -654,275 +375,3 @@ 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 biForest: - case biTaiga: - case biSwampland: - case biRiver: - case biFrozenOcean: - case biFrozenRiver: - case biIcePlains: - case biIceMountains: - case biForestHills: - case biTaigaHills: - case biExtremeHillsEdge: - case biExtremeHillsPlus: - case biExtremeHills: - case biJungle: - case biJungleHills: - case biJungleEdge: - case biDeepOcean: - case biStoneBeach: - case biColdBeach: - case biBirchForest: - case biBirchForestHills: - case biRoofedForest: - case biColdTaiga: - case biColdTaigaHills: - case biSavanna: - case biSavannaPlateau: - case biSunflowerPlains: - case biFlowerForest: - case biTaigaM: - case biSwamplandM: - case biIcePlainsSpikes: - case biJungleM: - case biJungleEdgeM: - case biBirchForestM: - case biBirchForestHillsM: - case biRoofedForestM: - case biColdTaigaM: - 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; - } - - case biExtremeHillsPlusM: - case biExtremeHillsM: - { - // Select the pattern to use - gravel, stone or grass: - 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.0) ? patStone.Get() : patGrass.Get(); - FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern); - return; - } - default: - { - ASSERT(!"Unhandled biome"); - return; - } - } // switch (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 = a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean ? patGravel.Get() : 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 d073f29e4..4027a94ca 100644 --- a/src/Generating/DistortedHeightmap.h +++ b/src/Generating/DistortedHeightmap.h @@ -24,17 +24,9 @@ class cDistortedHeightmap : - public cTerrainHeightGen, - public cTerrainCompositionGen + public cTerrainShapeGen { public: - /// Structure used for storing block patterns for columns - struct sBlockInfo - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - } ; - cDistortedHeightmap(int a_Seed, cBiomeGenPtr a_BiomeGen); protected: @@ -52,8 +44,6 @@ 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; @@ -71,9 +61,9 @@ protected: cTerrainHeightGenPtr m_UnderlyingHeiGen; /** Cache for m_UnderlyingHeiGen. */ - cHeiGenCache m_HeightGen; + cHeiGenCache m_HeightGen; - /// Heightmap for the current chunk, before distortion (from m_HeightGen). Used for optimization. + /** Heightmap for the current chunk, before distortion (from m_HeightGen). Used for optimization. */ cChunkDef::HeightMap m_CurChunkHeights; // Per-biome terrain generator parameters: @@ -88,54 +78,30 @@ protected: 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) + /** 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) + /** 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 + /** Generates the m_DistortedHeightmap array for the current chunk. */ void GenerateHeightArray(void); - /// Calculates the heightmap value (before distortion) at the specified (floating-point) coords + /** 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 + /** 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 + /** 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 + /** 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; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - virtual void InitializeCompoGen(cIniFile & a_IniFile) override; + // cTerrainShapeGen overrides: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override; + virtual void InitializeShapeGen(cIniFile & a_IniFile) override; } ; diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 3f328868d..bd45cb2a4 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -258,9 +258,9 @@ protected: //////////////////////////////////////////////////////////////////////////////// // cDungeonRoomsFinisher: -cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainHeightGenPtr a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) : +cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainShapeGenPtr a_ShapeGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) : super(a_Seed + 100, a_GridSize, a_GridSize, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 1024), - m_HeightGen(a_HeightGen), + m_ShapeGen(a_ShapeGen), m_MaxHalfSize((a_MaxSize + 1) / 2), m_MinHalfSize((a_MinSize + 1) / 2), m_HeightProbability(cChunkDef::Height) @@ -293,10 +293,14 @@ cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int int ChunkX, ChunkZ; int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ; cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ); + /* + // TODO cChunkDef::HeightMap HeightMap; m_HeightGen->GenHeightMap(ChunkX, ChunkZ, HeightMap); int Height = cChunkDef::GetHeight(HeightMap, RelX, RelZ); // Max room height at {a_OriginX, a_OriginZ} Height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, Height - 5); + */ + int Height = 62; // Create the dungeon room descriptor: return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, Height, m_Noise)); diff --git a/src/Generating/DungeonRoomsFinisher.h b/src/Generating/DungeonRoomsFinisher.h index 09dd0448a..e5828f989 100644 --- a/src/Generating/DungeonRoomsFinisher.h +++ b/src/Generating/DungeonRoomsFinisher.h @@ -23,15 +23,15 @@ class cDungeonRoomsFinisher : public: /** Creates a new dungeon room finisher. - a_HeightGen is the underlying height generator, so that the rooms can always be placed under the terrain. + a_ShapeGen is the underlying terrain shape generator, so that the rooms can always be placed under the terrain. a_MaxSize and a_MinSize are the maximum and minimum sizes of the room's internal (air) area, in blocks across. a_HeightDistrib is the string defining the height distribution for the rooms (cProbabDistrib format). */ - cDungeonRoomsFinisher(cTerrainHeightGenPtr a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib); + cDungeonRoomsFinisher(cTerrainShapeGenPtr a_ShapeGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib); protected: - /** The height gen that is used for limiting the rooms' Y coords */ - cTerrainHeightGenPtr m_HeightGen; + /** The shape gen that is used for limiting the rooms' Y coords */ + cTerrainShapeGenPtr m_ShapeGen; /** Maximum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 3 (vanilla). */ int m_MaxHalfSize; diff --git a/src/Generating/EndGen.cpp b/src/Generating/EndGen.cpp index 0111d2fa3..89d6117bb 100644 --- a/src/Generating/EndGen.cpp +++ b/src/Generating/EndGen.cpp @@ -147,13 +147,14 @@ bool cEndGen::IsChunkOutsideRange(int a_ChunkX, int a_ChunkZ) -void cEndGen::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cEndGen::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { + // If the chunk is outside out range, fill the shape with zeroes: if (IsChunkOutsideRange(a_ChunkX, a_ChunkZ)) { - for (size_t i = 0; i < ARRAYCOUNT(a_HeightMap); i++) + for (size_t i = 0; i < ARRAYCOUNT(a_Shape); i++) { - a_HeightMap[i] = 0; + a_Shape[i] = 0; } return; } @@ -165,15 +166,14 @@ void cEndGen::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_ { for (int x = 0; x < cChunkDef::Width; x++) { - cChunkDef::SetHeight(a_HeightMap, x, z, MaxY); - for (int y = MaxY; y > 0; y--) + for (int y = 0; y < MaxY; y++) { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= 0) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } - } // for y + a_Shape[(x + 16 * z) * 256 + y] = (m_NoiseArray[y * 17 * 17 + z * 17 + z] > 0) ? 1 : 0; + } + for (int y = MaxY; y < cChunkDef::Height; y++) + { + a_Shape[(x + 16 * z) * 256 + y] = 0; + } } // for x } // for z } @@ -182,30 +182,18 @@ void cEndGen::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_ -void cEndGen::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cEndGen::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { - if (IsChunkOutsideRange(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ())) - { - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - return; - } - - PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - int MaxY = std::min((int)(1.75 * m_IslandSizeY + 1), cChunkDef::Height - 1); + a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - for (int y = MaxY; y > 0; y--) + for (int y = 0; y < cChunkDef::Height; y++) { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= 0) - { - a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_END_STONE, 0); - } - else + if (a_Shape[(x + 16 * z) * 256 + y] != 0) { - a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_AIR, 0); + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_END_STONE); } } // for y } // for x diff --git a/src/Generating/EndGen.h b/src/Generating/EndGen.h index 322061810..e4c874014 100644 --- a/src/Generating/EndGen.h +++ b/src/Generating/EndGen.h @@ -17,7 +17,7 @@ class cEndGen : - public cTerrainHeightGen, + public cTerrainShapeGen, public cTerrainCompositionGen { public: @@ -59,10 +59,10 @@ protected: /// Returns true if the chunk is outside of the island's dimensions bool IsChunkOutsideRange(int a_ChunkX, int a_ChunkZ); - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + // cTerrainShapeGen overrides: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 1d9f1e3aa..86f934c16 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -15,7 +15,6 @@ - //////////////////////////////////////////////////////////////////////////////// // cHeiGenFlat: @@ -133,15 +132,6 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap -void cHeiGenCache::InitializeHeightGen(cIniFile & a_IniFile) -{ - m_HeiGenToCache->InitializeHeightGen(a_IniFile); -} - - - - - bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height) { for (int i = 0; i < m_CacheSize; i++) @@ -750,43 +740,51 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB } a_CacheOffByDefault = false; - cTerrainHeightGen * res = nullptr; - if (NoCaseCompare(HeightGenName, "flat") == 0) + cTerrainHeightGenPtr res; + if (NoCaseCompare(HeightGenName, "Flat") == 0) { - res = new cHeiGenFlat; + res = std::make_shared(); a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data } else if (NoCaseCompare(HeightGenName, "classic") == 0) { - res = new cHeiGenClassic(a_Seed); + res = std::make_shared(a_Seed); } else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0) { - res = new cDistortedHeightmap(a_Seed, a_BiomeGen); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } else if (NoCaseCompare(HeightGenName, "End") == 0) { - res = new cEndGen(a_Seed); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } else if (NoCaseCompare(HeightGenName, "MinMax") == 0) { - res = new cHeiGenMinMax(a_Seed, a_BiomeGen); + res = std::make_shared(a_Seed, a_BiomeGen); } else if (NoCaseCompare(HeightGenName, "Mountains") == 0) { - res = new cHeiGenMountains(a_Seed); + res = std::make_shared(a_Seed); } else if (NoCaseCompare(HeightGenName, "BiomalNoise3D") == 0) { - res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } else if (NoCaseCompare(HeightGenName, "Noise3D") == 0) { - res = new cNoise3DComposable(a_Seed); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } - else if (NoCaseCompare(HeightGenName, "biomal") == 0) + else if (NoCaseCompare(HeightGenName, "Biomal") == 0) { - res = new cHeiGenBiomal(a_Seed, a_BiomeGen); + res = std::make_shared(a_Seed, a_BiomeGen); /* // Performance-testing: @@ -805,15 +803,14 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB { // No match found, force-set the default and retry LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str()); - a_IniFile.DeleteValue("Generator", "HeightGen"); a_IniFile.SetValue("Generator", "HeightGen", "Biomal"); return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); } // Read the settings: res->InitializeHeightGen(a_IniFile); - - return cTerrainHeightGenPtr(res); + + return res; } diff --git a/src/Generating/HeiGen.h b/src/Generating/HeiGen.h index 6ae5ba362..d91ace3bd 100644 --- a/src/Generating/HeiGen.h +++ b/src/Generating/HeiGen.h @@ -2,10 +2,12 @@ // HeiGen.h /* -Interfaces to the various height generators: +Interfaces to the various height-based terrain shape generators: - cHeiGenFlat - cHeiGenClassic - cHeiGenBiomal + +Also implements the heightmap cache */ @@ -21,26 +23,7 @@ Interfaces to the various height generators: -class cHeiGenFlat : - public cTerrainHeightGen -{ -public: - cHeiGenFlat(void) : m_Height(5) {} - -protected: - - int m_Height; - - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; -} ; - - - - - -/// A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation +/** A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation */ class cHeiGenCache : public cTerrainHeightGen { @@ -50,15 +33,11 @@ public: // cTerrainHeightGen overrides: virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; - /// Retrieves height at the specified point in the cache, returns true if found, false if not found + /** 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: - - cTerrainHeightGenPtr m_HeiGenToCache; - struct sCacheData { int m_ChunkX; @@ -66,6 +45,9 @@ protected: 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 int m_CacheSize; int * m_CacheOrder; // MRU-ized order, indices into m_CacheData array @@ -81,6 +63,25 @@ protected: +class cHeiGenFlat : + public cTerrainHeightGen +{ +public: + cHeiGenFlat(void) : m_Height(5) {} + +protected: + + int m_Height; + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + virtual void InitializeHeightGen(cIniFile & a_IniFile) override; +} ; + + + + + class cHeiGenClassic : public cTerrainHeightGen { diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 4e45aa18b..da4632de4 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -458,110 +458,53 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) NOISE_DATATYPE BaseNoise[5 * 5]; NOISE_DATATYPE BlockX = static_cast(a_ChunkX * cChunkDef::Width); NOISE_DATATYPE BlockZ = static_cast(a_ChunkZ * cChunkDef::Width); - // Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z": - m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace); - m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); - m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x": + m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace); + m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); + m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); // Calculate the final noise based on the partial noises: - for (int y = 0; y < 33; y++) + for (int z = 0; z < 5; z++) { - NOISE_DATATYPE AddHeight = (static_cast(y * 8) - m_MidPoint) * m_HeightAmplification; - - // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: - if (AddHeight < 0) - { - AddHeight *= 4; - } - - for (int z = 0; z < 5; z++) + for (int x = 0; x < 5; x++) { - for (int x = 0; x < 5; x++) + NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z]; + for (int y = 0; y < 33; y++) { - int idx = x + 5 * z + 5 * 5 * y; - Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z]; + NOISE_DATATYPE AddHeight = (static_cast(y * 8) - m_MidPoint) * m_HeightAmplification; + + // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: + if (AddHeight < 0) + { + AddHeight *= 4; + } + + int idx = 33 * x + 33 * 5 * z + y; + Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } } } - LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); + LinearUpscale3DArray(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4); } -void cNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cNoise3DComposable::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); + // Translate the noise array into Shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel); - for (int y = cChunkDef::Height - 1; y > m_SeaLevel; y--) - { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= m_AirThreshold) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } - } // for y - } // for x - } // for z -} - - - - - -void cNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - - // Make basic terrain composition: - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - int LastAir = a_ChunkDesc.GetHeight(x, z) + 1; - bool HasHadWater = false; - for (int y = LastAir; y < m_SeaLevel; y++) + for (int y = 0; y < cChunkDef::Height; y++) { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); + a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1; } - for (int y = LastAir - 1; y > 0; y--) - { - if (m_NoiseArray[x + 17 * z + 17 * 17 * y] > m_AirThreshold) - { - // "air" part - LastAir = y; - if (y < m_SeaLevel) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); - HasHadWater = true; - } - continue; - } - // "ground" part: - if (LastAir - y > 4) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE); - continue; - } - if (HasHadWater) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND); - } - else - { - a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); - } - } // for y - a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); } // for x } // for z } @@ -671,21 +614,23 @@ void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_Ch NOISE_DATATYPE BaseNoise[5 * 5]; NOISE_DATATYPE BlockX = static_cast(a_ChunkX * cChunkDef::Width); NOISE_DATATYPE BlockZ = static_cast(a_ChunkZ * cChunkDef::Width); - // Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z": - m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace); - m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); - m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x": + m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace); + m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); + m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); // Calculate the final noise based on the partial noises: - for (int y = 0; y < 33; y++) + for (int z = 0; z < 5; z++) { - NOISE_DATATYPE BlockHeight = static_cast(y * 8); - for (int z = 0; z < 5; z++) + for (int x = 0; x < 5; x++) { - for (int x = 0; x < 5; x++) + NOISE_DATATYPE curMidPoint = MidPoint[x + 5 * z]; + NOISE_DATATYPE curHeightAmp = HeightAmp[x + 5 * z]; + NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z]; + for (int y = 0; y < 33; y++) { - NOISE_DATATYPE AddHeight = (BlockHeight - MidPoint[x + 5 * z]) * HeightAmp[x + 5 * z]; + NOISE_DATATYPE AddHeight = (static_cast(y * 8) - curMidPoint) * curHeightAmp; // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: if (AddHeight < 0) @@ -693,12 +638,12 @@ void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_Ch AddHeight *= 4; } - int idx = x + 5 * z + 5 * 5 * y; - Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z]; + int idx = 33 * x + y + 33 * 5 * z; + Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } } } - LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); + LinearUpscale3DArray(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4); } @@ -778,78 +723,19 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE - -void cBiomalNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cBiomalNoise3DComposable::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); + // Translate the noise array into Shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel); - for (int y = cChunkDef::Height - 1; y > m_SeaLevel; y--) - { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= m_AirThreshold) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } - } // for y - } // for x - } // for z -} - - - - - -void cBiomalNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - - // Make basic terrain composition: - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - int LastAir = a_ChunkDesc.GetHeight(x, z) + 1; - bool HasHadWater = false; - for (int y = LastAir; y < m_SeaLevel; y++) + for (int y = 0; y < cChunkDef::Height; y++) { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); + a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1; } - for (int y = LastAir - 1; y > 0; y--) - { - if (m_NoiseArray[x + 17 * z + 17 * 17 * y] > m_AirThreshold) - { - // "air" part - LastAir = y; - if (y < m_SeaLevel) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); - HasHadWater = true; - } - continue; - } - // "ground" part: - if (LastAir - y > 4) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE); - continue; - } - if (HasHadWater) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND); - } - else - { - a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); - } - } // for y - a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); } // for x } // for z } @@ -857,3 +743,4 @@ void cBiomalNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) + diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index ba541fbcc..eaac182ba 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -69,8 +69,7 @@ protected: class cNoise3DComposable : - public cTerrainHeightGen, - public cTerrainCompositionGen + public cTerrainShapeGen { public: cNoise3DComposable(int a_Seed); @@ -127,12 +126,8 @@ protected: void GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ); // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override; + virtual void InitializeShapeGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } } ; @@ -140,8 +135,7 @@ protected: class cBiomalNoise3DComposable : - public cTerrainHeightGen, - public cTerrainCompositionGen + public cTerrainShapeGen { public: cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_BiomeGen); @@ -194,7 +188,7 @@ protected: // 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 + NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // 257 * x + y + 257 * 17 * z /** Weights for summing up neighboring biomes. */ NOISE_DATATYPE m_Weight[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1]; @@ -212,13 +206,9 @@ protected: /** Returns the parameters for the specified biome. */ void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint); - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(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 { Initialize(a_IniFile); } } ; diff --git a/src/Generating/ShapeGen.cpp b/src/Generating/ShapeGen.cpp new file mode 100644 index 000000000..750b34e10 --- /dev/null +++ b/src/Generating/ShapeGen.cpp @@ -0,0 +1,140 @@ + +// ShapeGen.cpp + +// Implements the function to create a cTerrainShapeGen descendant based on INI file settings + +#include "Globals.h" +#include "HeiGen.h" +#include "../IniFile.h" +#include "DistortedHeightmap.h" +#include "EndGen.h" +#include "Noise3DGenerator.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cTerrainHeightToShapeGen: + +/** Converts old-style height-generators into new-style shape-generators. */ +class cTerrainHeightToShapeGen: + public cTerrainShapeGen +{ +public: + cTerrainHeightToShapeGen(cTerrainHeightGenPtr a_HeightGen): + m_HeightGen(a_HeightGen) + { + } + + + // cTerrainShapeGen overrides: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override + { + // Generate the heightmap: + cChunkDef::HeightMap heightMap; + m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, heightMap); + + // Convert from heightmap to shape: + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + HEIGHTTYPE height = cChunkDef::GetHeight(heightMap, x, z) + 1; + Byte * shapeColumn = &(a_Shape[(x + 16 * z) * 256]); + for (int y = 0; y < height; y++) + { + shapeColumn[y] = 1; + } + for (int y = height; y < cChunkDef::Height; y++) + { + shapeColumn[y] = 0; + } + } // for x + } // for z + } + + + virtual void InitializeShapeGen(cIniFile & a_IniFile) override + { + m_HeightGen->InitializeHeightGen(a_IniFile); + } + +protected: + /** The height generator being converted. */ + cTerrainHeightGenPtr m_HeightGen; +}; + +typedef SharedPtr cTerrainHeightToShapeGenPtr; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cTerrainShapeGen: + +cTerrainShapeGenPtr cTerrainShapeGen::CreateShapeGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault) +{ + AString shapeGenName = a_IniFile.GetValueSet("Generator", "ShapeGen", ""); + if (shapeGenName.empty()) + { + 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) + { + cTerrainHeightGenPtr heightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); + if (heightGen != nullptr) + { + return std::make_shared(heightGen); + } + + // The height gen was not recognized; several heightgens were promoted to shape gens, so let's try them instead: + shapeGenName = a_IniFile.GetValue("Generator", "HeightGen", ""); + if (shapeGenName.empty()) + { + LOGWARNING("[Generator] ShapeGen set to HeightMap, but HeightGen not set. Reverting to \"BiomalNoise3D\"."); + shapeGenName = "BiomalNoise3D"; + a_IniFile.SetValue("Generator", "ShapeGen", shapeGenName); + } + } + + // Choose the shape generator based on the name: + a_CacheOffByDefault = false; + cTerrainShapeGenPtr res; + if (NoCaseCompare(shapeGenName, "DistortedHeightmap") == 0) + { + res = std::make_shared(a_Seed, a_BiomeGen); + } + else if (NoCaseCompare(shapeGenName, "End") == 0) + { + res = std::make_shared(a_Seed); + } + else if (NoCaseCompare(shapeGenName, "BiomalNoise3D") == 0) + { + res = std::make_shared(a_Seed, a_BiomeGen); + } + else if (NoCaseCompare(shapeGenName, "Noise3D") == 0) + { + res = std::make_shared(a_Seed); + } + else + { + // No match found, force-set the default and retry + LOGWARN("Unknown ShapeGen \"%s\", using \"BiomalNoise3D\" instead.", shapeGenName.c_str()); + 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; +} + + + + diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp index bdefcd8c1..1c83cf78f 100644 --- a/src/Generating/StructGen.cpp +++ b/src/Generating/StructGen.cpp @@ -37,10 +37,12 @@ void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc) 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; m_BiomeGen->GenBiomes (BaseX, BaseZ, WorkerDesc.GetBiomeMap()); - m_HeightGen->GenHeightMap (BaseX, BaseZ, WorkerDesc.GetHeightMap()); - m_CompositionGen->ComposeTerrain(WorkerDesc); - // TODO: Free the entity lists + m_ShapeGen->GenShape (BaseX, BaseZ, workerShape); + m_CompositionGen->ComposeTerrain(WorkerDesc, workerShape); } else { @@ -390,7 +392,7 @@ void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc) } cBlockArea Lake; - CreateLakeImage(ChunkX + x, ChunkZ + z, Lake); + CreateLakeImage(ChunkX + x, ChunkZ + z, a_ChunkDesc.GetMinHeight(), Lake); int OfsX = Lake.GetOriginX() + x * cChunkDef::Width; int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width; @@ -404,25 +406,13 @@ void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc) -void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake) +void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea & a_Lake) { a_Lake.Create(16, 8, 16); a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy - // Find the minimum height in this chunk: - cChunkDef::HeightMap HeightMap; - m_HeiGen->GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap); - HEIGHTTYPE MinHeight = HeightMap[0]; - for (size_t i = 1; i < ARRAYCOUNT(HeightMap); i++) - { - if (HeightMap[i] < MinHeight) - { - MinHeight = HeightMap[i]; - } - } - // 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 - MinHeight = std::max(MinHeight - 6, 2); + int MinHeight = std::max(a_MaxLakeHeight - 6, 2); int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11; // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8; diff --git a/src/Generating/StructGen.h b/src/Generating/StructGen.h index 906fdd722..0c5efe622 100644 --- a/src/Generating/StructGen.h +++ b/src/Generating/StructGen.h @@ -24,11 +24,11 @@ class cStructGenTrees : public cFinishGen { public: - cStructGenTrees(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen, cTerrainCompositionGenPtr a_CompositionGen) : + cStructGenTrees(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, cTerrainCompositionGenPtr a_CompositionGen) : m_Seed(a_Seed), m_Noise(a_Seed), m_BiomeGen(a_BiomeGen), - m_HeightGen(a_HeightGen), + m_ShapeGen(a_ShapeGen), m_CompositionGen(a_CompositionGen) {} @@ -37,12 +37,12 @@ protected: int m_Seed; cNoise m_Noise; cBiomeGenPtr m_BiomeGen; - cTerrainHeightGenPtr m_HeightGen; + 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_BlockX. - Parts of the tree outside the chunk are stored in a_OutsideX + Parts of the tree inside the chunk are applied to a_ChunkDesc. + Parts of the tree outside the chunk are stored in a_OutsideXYZ */ void GenerateSingleTree( int a_ChunkX, int a_ChunkZ, int a_Seq, @@ -51,7 +51,7 @@ protected: sSetBlockVector & a_OutsideOther ) ; - /// Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow + /** 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, cChunkDesc & a_ChunkDesc, @@ -124,27 +124,30 @@ class cStructGenLakes : public cFinishGen { public: - cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainHeightGenPtr a_HeiGen, int a_Probability) : + cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainShapeGenPtr a_ShapeGen, int a_Probability) : m_Noise(a_Seed), m_Seed(a_Seed), m_Fluid(a_Fluid), - m_HeiGen(a_HeiGen), + m_ShapeGen(a_ShapeGen), m_Probability(a_Probability) { } protected: - cNoise m_Noise; - int m_Seed; - BLOCKTYPE m_Fluid; - cTerrainHeightGenPtr m_HeiGen; - int m_Probability; ///< Chance, 0 .. 100, of a chunk having the lake + cNoise m_Noise; + int m_Seed; + BLOCKTYPE m_Fluid; + cTerrainShapeGenPtr m_ShapeGen; + + /** 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, cBlockArea & a_Lake); + /** 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); } ; diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index a9b359b6a..f7d9a8316 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -18,8 +18,8 @@ /* How village generating works: -By descending from a cGridStructGen, a semi-random grid is generated. A village may be generated for each of -the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all +By descending from a cGridStructGen, a semi-random (jitter) grid is generated. A village may be generated for each +of the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell is left village-less. @@ -125,7 +125,7 @@ public: m_Noise(a_Seed), m_MaxSize(a_MaxSize), m_Density(a_Density), - m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize), + m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, cChunkDef::Height - 1, a_OriginZ + a_MaxSize), m_Prefabs(a_Prefabs), m_HeightGen(a_HeightGen), m_RoadBlock(a_RoadBlock), -- cgit v1.2.3 From 5584144be2f0747d35f0828413d5441af4a277ee Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Thu, 13 Nov 2014 10:44:36 +0100 Subject: First implementation for the LargeOakTree --- src/Generating/Trees.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++- src/Generating/Trees.h | 6 +++ 2 files changed, 110 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 7fd6d6f07..3c695ad20 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -61,7 +61,7 @@ static const sCoords BigO3[] = static const sCoords BigO4[] = // Part of Big Jungle tree { - /* -4 */ {-2, -4}, {-1, -4}, {0, -4}, {1, -4}, {2, -4}, + /* -4 */ {-2, -4}, {-1, -4}, {0, -4}, {1, -4}, {2, -4}, /* -3 */ {-3, -3}, {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, {3, -3}, /* -2 */ {-4, -2}, {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, {4, -2}, /* -1 */ {-4, -1}, {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, {4, -1}, @@ -361,7 +361,109 @@ void GetSmallAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a void GetLargeAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { - // TODO + int Height = 7 + a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 4; + + // Array with possible directions for a branch to go to. + const Vector3d AvailableDirections[] = + { + { -1, 0, 0 }, { 0, 0, -1 }, + { -1, 0, 1 }, { -1, 0, -1 }, + { 1, 0, 1 }, { 1, 0, -1 }, + { 1, 0, 0 }, { 0, 0, 1 }, + + { -0.5, 0, 0 }, { 0, 0, -0.5 }, + { -0.5, 0, 0.5 }, { -0.5, 0, -0.5 }, + { 0.5, 0, 0.5 }, { 0.5, 0, -0.5 }, + { 0.5, 0, 0 }, { 0, 0, 0.5 }, + + { -1, 0.5, 0 }, { 0, 0.5, -1 }, + { -1, 0.5, 1 }, { -1, 0.5, -1 }, + { 1, 0.5, 1 }, { 1, 0.5, -1 }, + { 1, 0.5, 0 }, { 0, 0.5, 1 }, + + { -0.5, 0.5, 0 }, { 0, 0.5, -0.5 }, + { -0.5, 0.5, 0.5 }, { -0.5, 0.5, -0.5 }, + { 0.5, 0.5, 0.5 }, { 0.5, 0.5, -0.5 }, + { 0.5, 0.5, 0 }, { 0, 0.5, 0.5 }, + + }; + + // Create branches + for (int i = 4; i < Height; i++) + { + // Get a direction for the trunk to go to. + Vector3d BranchStartDirection = AvailableDirections[a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + i, a_BlockZ) % ARRAYCOUNT(AvailableDirections)]; + Vector3d BranchDirection = AvailableDirections[a_Noise.IntNoise3DInt(a_BlockX, a_BlockY / i, a_BlockZ) % ARRAYCOUNT(AvailableDirections)] / 3; + + int BranchLength = 2 + a_Noise.IntNoise3DInt(a_BlockX * a_Seq, a_BlockY * a_Seq, a_BlockZ * a_Seq) % 3; + GetLargeAppleTreeBranch(a_BlockX, a_BlockY + i, a_BlockZ, BranchLength, BranchStartDirection, BranchDirection, a_BlockY + Height, a_Noise, a_LogBlocks); + } + + // Place leaves + for (auto itr : a_LogBlocks) + { + // Get the log's X and Z coordinates + int X = itr.ChunkX * 16 + itr.x; + int Z = itr.ChunkZ * 16 + itr.z; + + a_OtherBlocks.push_back(sSetBlock(X, itr.y - 2, Z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE)); + PushCoordBlocks(X, itr.y - 2, Z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); + for (int y = -1; y <= 1; y++) + { + PushCoordBlocks (X, itr.y + y, Z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); + } + PushCoordBlocks(X, itr.y + 2, Z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); + a_OtherBlocks.push_back(sSetBlock(X, itr.y + 2, Z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE)); + } + + // 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)); + } +} + + + + + +void GetLargeAppleTreeBranch(int a_BlockX, int a_BlockY, int a_BlockZ, int a_BranchLength, Vector3d a_StartDirection, Vector3d a_Direction, int a_TreeHeight, cNoise & a_Noise, sSetBlockVector & a_LogBlocks) +{ + Vector3d CurrentPos = Vector3d(a_BlockX, a_BlockY, a_BlockZ); + Vector3d Direction = a_StartDirection; + for (int i = 0; i < a_BranchLength; i++) + { + CurrentPos += Direction; + if (CurrentPos.y >= a_TreeHeight) + { + return; + } + Direction -= a_Direction; + Direction.clamp(-1.0, 1.0); + a_LogBlocks.push_back(sSetBlock(FloorC(CurrentPos.x), FloorC(CurrentPos.y), FloorC(CurrentPos.z), E_BLOCK_LOG, GetLogMetaFromDirection(E_META_LOG_APPLE, Direction))); + } +} + + + + + +NIBBLETYPE GetLogMetaFromDirection(NIBBLETYPE a_BlockMeta, Vector3d a_Direction) +{ + a_Direction.abs(); + + if ((a_Direction.y > a_Direction.x) && (a_Direction.y > a_Direction.z)) + { + return a_BlockMeta; + } + else if (a_Direction.x > a_Direction.z) + { + return a_BlockMeta + 4; + } + else + { + return a_BlockMeta + 8; + } } diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h index c9eb7de80..b6b61fe7b 100644 --- a/src/Generating/Trees.h +++ b/src/Generating/Trees.h @@ -62,6 +62,12 @@ void GetSmallAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a /// Generates an image of a large (branching) apple tree void GetLargeAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); +/// Generates a branch for a large apple tree +void GetLargeAppleTreeBranch(int a_BlockX, int a_BlockY, int a_BlockZ, int a_BranchLength, Vector3d a_StartDirection, Vector3d a_Direction, int a_TreeHeight, cNoise & a_Noise, sSetBlockVector & a_LogBlocks); + +/// Returns the meta for a log from the given direction +NIBBLETYPE GetLogMetaFromDirection(NIBBLETYPE a_BlockMeta, Vector3d a_Direction); + /// Generates an image of a random birch tree void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); -- cgit v1.2.3 From 7a3b3aeb3c28b7ba899d6dff2b5e160a95529f40 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 13 Nov 2014 21:28:50 +0100 Subject: Gen refactor: Implemented CompositedHeiGen. This fixes crashes in the Village generator due to the missing generator. --- src/Generating/CMakeLists.txt | 1 + src/Generating/CompoGen.cpp | 2 + src/Generating/CompoGen.h | 1 + src/Generating/CompoGenBiomal.cpp | 214 --------------------------------- src/Generating/ComposableGenerator.cpp | 13 +- src/Generating/CompositedHeiGen.h | 49 ++++++++ src/Generating/HeiGen.cpp | 45 +++++++ src/Generating/HeiGen.h | 32 +++++ src/Generating/StructGen.cpp | 1 + 9 files changed, 141 insertions(+), 217 deletions(-) create mode 100644 src/Generating/CompositedHeiGen.h (limited to 'src/Generating') diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index 047452bbb..dcb4bb3a7 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -42,6 +42,7 @@ SET (HDRS CompoGen.h CompoGenBiomal.h ComposableGenerator.h + CompositedHeiGen.h DistortedHeightmap.h DungeonRoomsFinisher.h EndGen.h diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index ef13b7c6b..db43e34b6 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -417,6 +417,7 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc:: // 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; @@ -436,6 +437,7 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc:: m_CacheOrder[0] = Idx; memcpy(m_CacheData[Idx].m_BlockTypes, a_ChunkDesc.GetBlockTypes(), sizeof(a_ChunkDesc.GetBlockTypes())); memcpy(m_CacheData[Idx].m_BlockMetas, a_ChunkDesc.GetBlockMetasUncompressed(), sizeof(a_ChunkDesc.GetBlockMetasUncompressed())); + memcpy(m_CacheData[Idx].m_HeightMap, a_ChunkDesc.GetHeightMap(), sizeof(a_ChunkDesc.GetHeightMap())); m_CacheData[Idx].m_ChunkX = ChunkX; m_CacheData[Idx].m_ChunkZ = ChunkZ; } diff --git a/src/Generating/CompoGen.h b/src/Generating/CompoGen.h index 16c00c13d..03df0cf25 100644 --- a/src/Generating/CompoGen.h +++ b/src/Generating/CompoGen.h @@ -132,6 +132,7 @@ protected: int m_ChunkZ; cChunkDef::BlockTypes m_BlockTypes; 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 diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp index 1e3363606..0bb7f4802 100644 --- a/src/Generating/CompoGenBiomal.cpp +++ b/src/Generating/CompoGenBiomal.cpp @@ -570,220 +570,6 @@ protected: return patDirt.Get(); } } - - - - #if 0 - /** Fills a single column with grass-based terrain (grass or water, dirt, stone). */ - void FillColumnGrass(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) - { - static const PatternItem pattern[] = - { - { E_BLOCK_GRASS, 0}, - { E_BLOCK_DIRT, 0}, - { E_BLOCK_DIRT, 0}, - { E_BLOCK_DIRT, 0}, - } ; - FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); - } - - - - /** Fills a single column with grass-based terrain (grass or water, dirt, stone). */ - void FillColumnStone(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) - { - static const PatternItem pattern[] = - { - { E_BLOCK_STONE, 0}, - } ; - FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); - } - - - - /** Fills a single column with Mesa-like terrain (variations of clay). */ - void FillColumnMesa(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) - { - // Fill with grass and dirt on the very top of mesa plateaus: - size_t curIdx = 0; - for (int y = 255; y > m_MesaDirtLevel; y--) - { - if (a_ShapeColumn[y] > 0) - { - a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, (curIdx > 0) ? E_BLOCK_DIRT : E_BLOCK_GRASS); - curIdx += 1; - } - else - { - curIdx = 0; - } - } // for y - - // Fill with clays from the DirtLevel down to SandLevel: - for (int y = m_MesaDirtLevel; y > m_MesaSandLevel; y--) - { - if (a_ShapeColumn[y] > 0) - { - a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, m_MesaPattern[y].m_BlockType, m_MesaPattern[y].m_BlockMeta); - } - else - { - curIdx = 0; - } - } // for y - - // If currently air, switch to red sand pattern: - static const PatternItem redSandPattern[] = - { - { E_BLOCK_SAND, E_META_SAND_RED}, - { E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE}, - { E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE}, - { E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE}, - }; - Pattern pattern; - size_t patternSize; - if (curIdx == 0) - { - pattern = redSandPattern; - patternSize = ARRAYCOUNT(redSandPattern); - } - else - { - pattern = m_MesaPattern + m_MesaSandLevel; - patternSize = static_cast(m_MesaSandLevel); - } - - // Fill with current pattern (MesaPattern or RedSand) until sealevel: - for (int y = m_MesaSandLevel; y > m_SeaLevel; y--) - { - if (a_ShapeColumn[y] > 0) - { - if (curIdx >= patternSize) - { - a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE); - } - else - { - a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, pattern[curIdx].m_BlockType, pattern[curIdx].m_BlockMeta); - } - curIdx += 1; - } - else - { - // Air resets the pattern to red sand: - curIdx = 0; - pattern = redSandPattern; - patternSize = ARRAYCOUNT(redSandPattern); - } - } // for y - - // If there is an ocean, fill it with water and then redsand: - int y = m_SeaLevel; - for (; y > 0; y--) - { - if ((a_ShapeColumn[y] == 0) || (curIdx >= ARRAYCOUNT(redSandPattern))) - { - // water pocket or out of red sand pattern, use stone from now on - break; - } - a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, E_BLOCK_STAINED_CLAY, E_META_STAINED_CLAY_ORANGE); - curIdx = curIdx + 1; - } // for y - - // The rest should be filled with stone: - for (; y > 0; y--) - { - if (a_ShapeColumn[y] > 0) - { - a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); - } - } // for y - } - - - - /** Fills a single column with megataiga-based terrain (grass or podzol on top). */ - void FillColumnMegaTaiga(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) - { - // TODO - } - - - - /** Fills a single column with sand-based terrain (such as desert or beach). */ - void FillColumnSand(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) - { - static const PatternItem pattern[] = - { - { E_BLOCK_SAND, 0}, - { E_BLOCK_SAND, 0}, - { E_BLOCK_SAND, 0}, - { E_BLOCK_SANDSTONE, 0}, - } ; - FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); - } - - - - void FillColumnMycelium(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc) - { - static const PatternItem pattern[] = - { - { E_BLOCK_MYCELIUM, 0}, - { E_BLOCK_DIRT, 0}, - { E_BLOCK_DIRT, 0}, - { E_BLOCK_DIRT, 0}, - } ; - FillColumnPattern(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, pattern, ARRAYCOUNT(pattern)); - } - - - - /** Fills the column with the specified pattern, repeating it if there's an air pocket in between. */ - void FillColumnPattern(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc, Pattern a_Pattern, size_t a_PatternSize) - { - // Fill with pattern until sealevel: - size_t curIdx = 0; - for (int y = 255; y > m_SeaLevel; y--) - { - if (a_ShapeColumn[y] > 0) - { - // Continue with the pattern: - if (curIdx >= a_PatternSize) - { - a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); - } - else - { - a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[curIdx].m_BlockType, a_Pattern[curIdx].m_BlockMeta); - } - curIdx += 1; - } - else - { - // Air pocket, restart the pattern: - curIdx = 0; - } - } // for y - - // From sealevel downward use the ocean floor pattern: - FillOceanFloor(a_RelX, a_RelZ, a_ShapeColumn, a_ChunkDesc, a_Pattern, a_PatternSize, curIdx); - } - - - /** Fills the blocks from sealevel down to bottom with ocean-floor pattern. - a_PatternStartOffset specifies the offset at which to start the pattern, in case there was air just above. */ - void FillOceanFloor(int a_RelX, int a_RelZ, const Byte * a_ShapeColumn, cChunkDesc & a_ChunkDesc, Pattern a_Pattern, size_t a_PatternSize, size_t a_PatternStartOffset) - { - for (int y = m_SeaLevel; y > 0; y--) - { - if (a_ShapeColumn[y] > 0) - { - // TODO - } - } // for y - } - #endif } ; diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 5420e12ac..4192dfa72 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -19,6 +19,8 @@ #include "CompoGenBiomal.h" +#include "CompositedHeiGen.h" + #include "Caves.h" #include "DistortedHeightmap.h" #include "DungeonRoomsFinisher.h" @@ -173,7 +175,6 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a if (a_ChunkDesc.IsUsingDefaultComposition()) { m_CompositionGen->ComposeTerrain(a_ChunkDesc, shape); - ShouldUpdateHeightmap = true; } if (a_ChunkDesc.IsUsingDefaultFinish()) @@ -264,11 +265,17 @@ 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); - if (CompoGenCacheSize > 1) + if (CompoGenCacheSize > 0) { - m_CompositionGen = cTerrainCompositionGenPtr(new cCompoGenCache(m_CompositionGen, 32)); + m_CompositionGen = std::make_shared(m_CompositionGen, CompoGenCacheSize); } + + // Create a cache of the composited heightmaps, so that finishers may use it: + m_CompositedHeightCache = std::make_shared(std::make_shared(m_ShapeGen, m_CompositionGen), 16, 24); + // 24 subcaches of depth 16 each = 96 KiB of RAM. Acceptable, for the amount of work this saves. } diff --git a/src/Generating/CompositedHeiGen.h b/src/Generating/CompositedHeiGen.h new file mode 100644 index 000000000..fa33a7861 --- /dev/null +++ b/src/Generating/CompositedHeiGen.h @@ -0,0 +1,49 @@ + +// CompositedHeiGen.h + +// Declares the cCompositedHeiGen class representing a cTerrainHeightGen descendant that calculates heightmap of the composited terrain +// This is used to further cache heightmaps for chunks already generated for finishers that require only heightmap information + + + + + +#pragma once + +#include "ComposableGenerator.h" + + + + + +class cCompositedHeiGen: + public cTerrainHeightGen +{ +public: + cCompositedHeiGen(cTerrainShapeGenPtr a_ShapeGen, cTerrainCompositionGenPtr a_CompositionGen): + m_ShapeGen(a_ShapeGen), + m_CompositionGen(a_CompositionGen) + { + } + + + + // cTerrainheightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override + { + cChunkDesc::Shape shape; + m_ShapeGen->GenShape(a_ChunkX, a_ChunkZ, shape); + cChunkDesc desc(a_ChunkX, a_ChunkZ); + desc.SetHeightFromShape(shape); + m_CompositionGen->ComposeTerrain(desc, shape); + memcpy(a_HeightMap, desc.GetHeightMap(), sizeof(a_HeightMap)); + } + +protected: + cTerrainShapeGenPtr m_ShapeGen; + cTerrainCompositionGenPtr m_CompositionGen; +}; + + + + diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 86f934c16..61d087c17 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -149,6 +149,51 @@ bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_Rel +//////////////////////////////////////////////////////////////////////////////// +// cHeiGenMultiCache: + +cHeiGenMultiCache::cHeiGenMultiCache(cTerrainHeightGenPtr a_HeiGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches): + m_NumSubCaches(a_NumSubCaches) +{ + // Create the individual sub-caches: + m_SubCaches.reserve(a_NumSubCaches); + for (size_t i = 0; i < a_NumSubCaches; i++) + { + m_SubCaches.push_back(std::make_shared(a_HeiGenToCache, a_SubCacheSize)); + } +} + + + + + +void cHeiGenMultiCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +{ + // Get the subcache responsible for this chunk: + const size_t cacheIdx = ((size_t)a_ChunkX + m_CoeffZ * (size_t)a_ChunkZ) % m_NumSubCaches; + + // Ask the subcache: + m_SubCaches[cacheIdx]->GenHeightMap(a_ChunkX, a_ChunkZ, a_HeightMap); +} + + + + + +bool cHeiGenMultiCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height) +{ + // Get the subcache responsible for this chunk: + const size_t cacheIdx = ((size_t)a_ChunkX + m_CoeffZ * (size_t)a_ChunkZ) % m_NumSubCaches; + + // Ask the subcache: + return m_SubCaches[cacheIdx]->GetHeightAt(a_ChunkX, a_ChunkZ, a_RelX, a_RelZ, a_Height); +} + + + + + + //////////////////////////////////////////////////////////////////////////////// // cHeiGenClassic: diff --git a/src/Generating/HeiGen.h b/src/Generating/HeiGen.h index d91ace3bd..fe0a023e4 100644 --- a/src/Generating/HeiGen.h +++ b/src/Generating/HeiGen.h @@ -63,6 +63,38 @@ protected: +/** Caches heightmaps in multiple underlying caches to improve the distribution and lower the chain length. */ +class cHeiGenMultiCache: + public cTerrainHeightGen +{ +public: + cHeiGenMultiCache(cTerrainHeightGenPtr a_HeightGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches); + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) 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: + typedef SharedPtr cHeiGenCachePtr; + typedef std::vector cHeiGenCachePtrs; + + + /** The coefficient used to turn Z coords into index (x + Coeff * z). */ + static const size_t m_CoeffZ = 5; + + /** Number of sub-caches, pulled out of m_SubCaches.size() for performance reasons. */ + size_t m_NumSubCaches; + + /** The individual sub-caches. */ + cHeiGenCachePtrs m_SubCaches; +}; + + + + + class cHeiGenFlat : public cTerrainHeightGen { diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp index 1c83cf78f..ca8f0411f 100644 --- a/src/Generating/StructGen.cpp +++ b/src/Generating/StructGen.cpp @@ -42,6 +42,7 @@ void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc) cChunkDesc::Shape workerShape; m_BiomeGen->GenBiomes (BaseX, BaseZ, WorkerDesc.GetBiomeMap()); m_ShapeGen->GenShape (BaseX, BaseZ, workerShape); + WorkerDesc.SetHeightFromShape (workerShape); m_CompositionGen->ComposeTerrain(WorkerDesc, workerShape); } else -- cgit v1.2.3 From 2789fafeb7445a69ccd31e7867e5c9f27654725f Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 13 Nov 2014 21:47:39 +0100 Subject: Noise3D: Added oceans. --- src/Generating/Noise3DGenerator.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 4e45aa18b..d516b612c 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -756,10 +756,13 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE { switch (a_Biome) { + case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; // Needs verification case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; + case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; + case biOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; -- cgit v1.2.3 From 644240a0e5b03889fb202ff173337cdf389d197b Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 14 Nov 2014 22:17:11 +0100 Subject: Noise3D: Added jungles. --- src/Generating/Noise3DGenerator.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index d516b612c..91bdce458 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -762,6 +762,8 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; + case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; case biOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; -- cgit v1.2.3 From 30fa6a642c309b054e017aa5e07f62ed7c219dc7 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 15 Nov 2014 11:17:05 +0100 Subject: DungeonRooms: Changed to work with the new shape generators. --- src/Generating/DungeonRoomsFinisher.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index bd45cb2a4..7ab22c2c5 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -78,7 +78,8 @@ protected: - /** Decodes the position index along the room walls into a proper 2D position for a chest. */ + /** Decodes the position index along the room walls into a proper 2D position for a chest. + The Y coord of the returned vector specifies the chest's meta value*/ Vector3i DecodeChestCoords(int a_PosIdx, int a_SizeX, int a_SizeZ) { if (a_PosIdx < a_SizeX) @@ -293,17 +294,21 @@ cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int int ChunkX, ChunkZ; int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ; cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ); - /* - // TODO - cChunkDef::HeightMap HeightMap; - m_HeightGen->GenHeightMap(ChunkX, ChunkZ, HeightMap); - int Height = cChunkDef::GetHeight(HeightMap, RelX, RelZ); // Max room height at {a_OriginX, a_OriginZ} - Height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, Height - 5); - */ - int Height = 62; + cChunkDesc::Shape shape; + m_ShapeGen->GenShape(ChunkX, ChunkZ, shape); + int height = 0; + int idx = RelX * 256 + RelZ * 16 * 256; + for (int y = 6; y < cChunkDef::Height; y++) + { + if (shape[idx + y] != 0) + { + continue; + } + height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, y - 5); + } // Create the dungeon room descriptor: - return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, Height, m_Noise)); + return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, height, m_Noise)); } -- cgit v1.2.3 From 889aa7404dd37b862d8874c9d5545f51be19e17d Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 15 Nov 2014 20:23:47 +0100 Subject: ChunkDesc: Fixed comment about indexing. --- src/Generating/ChunkDesc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index b86041a7d..480106fb5 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -33,7 +33,7 @@ public: /** The datatype used to represent the entire chunk worth of shape. 0 = air 1 = solid - Indexed as [y + 256 * z + 256 * 16 * x]. */ + Indexed as [y + 256 * x + 256 * 16 * z]. */ typedef Byte Shape[256 * 16 * 16]; /** Uncompressed block metas, 1 meta per byte */ -- cgit v1.2.3 From b0bcd75732bef60409ac1390cf3fbe5cd89c6634 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 15 Nov 2014 20:24:15 +0100 Subject: Snow generator: Fixed failure at top of the world. --- src/Generating/FinishGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index b8afac09a..f67d59998 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -412,7 +412,7 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc) case biFrozenOcean: { int Height = a_ChunkDesc.GetHeight(x, z); - if (cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z))) + if (cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z)) && (Height < cChunkDef::Height - 1)) { a_ChunkDesc.SetBlockType(x, Height + 1, z, E_BLOCK_SNOW); a_ChunkDesc.SetHeight(x, z, Height + 1); -- cgit v1.2.3 From 564b9ad33711b45c59d3c001df1b9206c7cbf60e Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sat, 15 Nov 2014 21:45:24 +0100 Subject: Generator: Fixed crash with trees too high. --- src/Generating/StructGen.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp index ca8f0411f..2f685c808 100644 --- a/src/Generating/StructGen.cpp +++ b/src/Generating/StructGen.cpp @@ -100,7 +100,7 @@ void cStructGenTrees::GenerateSingleTree( int Height = a_ChunkDesc.GetHeight(x, z); - if ((Height <= 0) || (Height > 240)) + if ((Height <= 0) || (Height >= 230)) { return; } @@ -128,6 +128,11 @@ void cStructGenTrees::GenerateSingleTree( // Outside the chunk continue; } + if (itr->y >= cChunkDef::Height) + { + // Above the chunk, cut off (this shouldn't happen too often, we're limiting trees to y < 230) + continue; + } BLOCKTYPE Block = a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z); switch (Block) @@ -162,7 +167,7 @@ void cStructGenTrees::ApplyTreeImage( // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks for (sSetBlockVector::const_iterator itr = a_Image.begin(), end = a_Image.end(); itr != end; ++itr) { - if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ)) + if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ) && (itr->y < cChunkDef::Height)) { // Inside this chunk, integrate into a_ChunkDesc: switch (a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z)) -- cgit v1.2.3 From 95e59056a187fe51091b5ee4b3870fa94b7df12f Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 16 Nov 2014 19:02:37 +0100 Subject: BiomalNoise3D: Added more biomes. --- src/Generating/Noise3DGenerator.cpp | 78 ++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 13 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 91bdce458..f2af75999 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -756,19 +756,71 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE { switch (a_Biome) { - case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; - case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; // Needs verification - case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; - case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; - case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; - case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; - case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; - case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; - case biOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; - case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification - case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; - case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; - case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; + case biBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; + case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; + case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break; + case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; + case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; + case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; + case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biMushroomShore: a_HeightAmp = 0.15f; a_MidPoint = 15; break; + case biOcean: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; + case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; + case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; + case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + + /* + // Still missing: + case biColdTaiga: a_HeightAmp = 0.15f; a_MidPoint = 30; break; + case biColdTaigaHills: a_HeightAmp = 0.15f; a_MidPoint = 31; break; + case biColdTaigaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biDesertM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biExtremeHillsEdge: a_HeightAmp = 0.15f; a_MidPoint = 20; break; + case biExtremeHillsM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biExtremeHillsPlusM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 23; break; + case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biMegaSpruceTaiga: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biMegaTaiga: a_HeightAmp = 0.15f; a_MidPoint = 32; break; + case biMesa: a_HeightAmp = 0.15f; a_MidPoint = 37; break; + case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biMesaPlateau: a_HeightAmp = 0.15f; a_MidPoint = 39; break; + case biMesaPlateauF: a_HeightAmp = 0.15f; a_MidPoint = 38; break; + case biMesaPlateauFM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biMesaPlateauM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biMushroomIsland: a_HeightAmp = 0.15f; a_MidPoint = 14; break; + case biNether: a_HeightAmp = 0.15f; a_MidPoint = 68; break; + case biRoofedForest: a_HeightAmp = 0.15f; a_MidPoint = 29; break; + case biRoofedForestM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biSavanna: a_HeightAmp = 0.15f; a_MidPoint = 35; break; + case biSavannaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biSavannaPlateau: a_HeightAmp = 0.15f; a_MidPoint = 36; break; + case biSavannaPlateauM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biStoneBeach: a_HeightAmp = 0.15f; a_MidPoint = 25; break; + case biSunflowerPlains: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + case biTaiga: a_HeightAmp = 0.15f; a_MidPoint = 65; break; + case biTaigaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; + */ default: { -- cgit v1.2.3 From ff036c9cef7ba04cfbd96196570b2251874eac7a Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 16 Nov 2014 19:50:57 +0100 Subject: Changed comment Suggestion by xoft --- src/Generating/Trees.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 3c695ad20..be8b0cd6b 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -399,7 +399,7 @@ void GetLargeAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a GetLargeAppleTreeBranch(a_BlockX, a_BlockY + i, a_BlockZ, BranchLength, BranchStartDirection, BranchDirection, a_BlockY + Height, a_Noise, a_LogBlocks); } - // Place leaves + // Place leaves around each log block for (auto itr : a_LogBlocks) { // Get the log's X and Z coordinates -- cgit v1.2.3 From f9cfc36643b7cc0a2b8f46455d452beb6e444e0d Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 17 Nov 2014 16:50:28 +0100 Subject: Added cImprovedNoise implementation. --- src/Generating/Noise3DGenerator.cpp | 37 ++++--------------------------------- src/Generating/Noise3DGenerator.h | 6 +++--- 2 files changed, 7 insertions(+), 36 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index f2af75999..654e9d01f 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -61,35 +61,6 @@ public: -/** Linearly interpolates between two values. -Assumes that a_Ratio is in range [0, 1]. */ -inline static NOISE_DATATYPE Lerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio) -{ - return a_Val1 + (a_Val2 - a_Val1) * a_Ratio; -} - - - - - -/** Linearly interpolates between two values, clamping the ratio to [0, 1] first. */ -inline static NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio) -{ - if (a_Ratio < 0) - { - return a_Val1; - } - if (a_Ratio > 1) - { - return a_Val2; - } - return Lerp(a_Val1, a_Val2, a_Ratio); -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cNoise3DGenerator: @@ -249,10 +220,10 @@ void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DAT NOISE_DATATYPE NoiseW[DIM_X * DIM_Y * DIM_Z]; // Workspace that the noise calculation can use and trash // Our noise array has different layout, XZY, instead of regular chunk's XYZ, that's why the coords are "renamed" - NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width)) / m_FrequencyX; - NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((a_ChunkX + 1) * cChunkDef::Width) - 1) / m_FrequencyX; - NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width)) / m_FrequencyZ; - NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((a_ChunkZ + 1) * cChunkDef::Width) - 1) / m_FrequencyZ; + NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width)) / m_FrequencyX; + NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((a_ChunkX + 1) * cChunkDef::Width)) / m_FrequencyX; + NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width)) / m_FrequencyZ; + NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((a_ChunkZ + 1) * cChunkDef::Width)) / m_FrequencyZ; NOISE_DATATYPE StartY = 0; NOISE_DATATYPE EndY = ((NOISE_DATATYPE)256) / m_FrequencyY; diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index ba541fbcc..92cfc32b7 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -34,9 +34,9 @@ public: protected: // Linear interpolation step sizes, must be divisors of cChunkDef::Width and cChunkDef::Height, respectively: - static const int UPSCALE_X = 8; - static const int UPSCALE_Y = 4; - static const int UPSCALE_Z = 8; + 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; -- cgit v1.2.3 From 2467d29a4ec63936d0af20ae4d5cfb8e897e75be Mon Sep 17 00:00:00 2001 From: Mattes D Date: Tue, 18 Nov 2014 12:07:08 +0100 Subject: Moved all Noise-related files into a separate folder. --- src/Generating/BioGen.h | 2 +- src/Generating/Caves.h | 1 - src/Generating/ChunkDesc.cpp | 2 +- src/Generating/CompoGen.h | 2 +- src/Generating/DistortedHeightmap.h | 1 - src/Generating/EndGen.h | 2 +- src/Generating/FinishGen.cpp | 1 - src/Generating/FinishGen.h | 2 +- src/Generating/GridStructGen.h | 2 +- src/Generating/HeiGen.h | 2 +- src/Generating/MineShafts.h | 1 - src/Generating/Noise3DGenerator.h | 2 +- src/Generating/PieceGenerator.h | 2 +- src/Generating/Ravines.h | 1 - src/Generating/StructGen.h | 2 +- src/Generating/Trees.h | 2 +- 16 files changed, 11 insertions(+), 16 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/BioGen.h b/src/Generating/BioGen.h index 5fd0844d9..13fb40c5f 100644 --- a/src/Generating/BioGen.h +++ b/src/Generating/BioGen.h @@ -15,7 +15,7 @@ Interfaces to the various biome generators: #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" #include "../VoronoiMap.h" diff --git a/src/Generating/Caves.h b/src/Generating/Caves.h index 0e17acf9e..691ef3e62 100644 --- a/src/Generating/Caves.h +++ b/src/Generating/Caves.h @@ -13,7 +13,6 @@ #pragma once #include "GridStructGen.h" -#include "../Noise.h" diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index 020d3bd0f..042b688b7 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -7,7 +7,7 @@ #include "ChunkDesc.h" #include "../BlockArea.h" #include "../Cuboid.h" -#include "../Noise.h" +#include "../Noise/Noise.h" #include "../BlockEntities/BlockEntity.h" diff --git a/src/Generating/CompoGen.h b/src/Generating/CompoGen.h index b145b6ba3..c65a07fe8 100644 --- a/src/Generating/CompoGen.h +++ b/src/Generating/CompoGen.h @@ -17,7 +17,7 @@ #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/DistortedHeightmap.h b/src/Generating/DistortedHeightmap.h index d073f29e4..955e57a1e 100644 --- a/src/Generating/DistortedHeightmap.h +++ b/src/Generating/DistortedHeightmap.h @@ -11,7 +11,6 @@ #include "ComposableGenerator.h" #include "HeiGen.h" -#include "../Noise.h" diff --git a/src/Generating/EndGen.h b/src/Generating/EndGen.h index 322061810..c2278c1e1 100644 --- a/src/Generating/EndGen.h +++ b/src/Generating/EndGen.h @@ -10,7 +10,7 @@ #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index b8afac09a..42ecdf8a8 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -10,7 +10,6 @@ #include "Globals.h" #include "FinishGen.h" -#include "../Noise.h" #include "../BlockID.h" #include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway() #include "../Simulator/FireSimulator.h" diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 4a08d70c8..991a85787 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -16,7 +16,7 @@ #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" #include "../ProbabDistrib.h" diff --git a/src/Generating/GridStructGen.h b/src/Generating/GridStructGen.h index 03131fce9..b92fb2e9d 100644 --- a/src/Generating/GridStructGen.h +++ b/src/Generating/GridStructGen.h @@ -10,7 +10,7 @@ #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/HeiGen.h b/src/Generating/HeiGen.h index 6ae5ba362..b3c9483fb 100644 --- a/src/Generating/HeiGen.h +++ b/src/Generating/HeiGen.h @@ -15,7 +15,7 @@ Interfaces to the various height generators: #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/MineShafts.h b/src/Generating/MineShafts.h index 2850db571..efb11cfee 100644 --- a/src/Generating/MineShafts.h +++ b/src/Generating/MineShafts.h @@ -10,7 +10,6 @@ #pragma once #include "GridStructGen.h" -#include "../Noise.h" diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 92cfc32b7..8a6e97e1c 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -13,7 +13,7 @@ #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/PieceGenerator.h b/src/Generating/PieceGenerator.h index f06029280..43ffed7a2 100644 --- a/src/Generating/PieceGenerator.h +++ b/src/Generating/PieceGenerator.h @@ -20,7 +20,7 @@ Each uses a slightly different approach to generating: #include "../Defines.h" #include "../Cuboid.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/Ravines.h b/src/Generating/Ravines.h index 3e41c5ce6..b11037433 100644 --- a/src/Generating/Ravines.h +++ b/src/Generating/Ravines.h @@ -10,7 +10,6 @@ #pragma once #include "GridStructGen.h" -#include "../Noise.h" diff --git a/src/Generating/StructGen.h b/src/Generating/StructGen.h index 906fdd722..d3b0b5544 100644 --- a/src/Generating/StructGen.h +++ b/src/Generating/StructGen.h @@ -14,7 +14,7 @@ #pragma once #include "ComposableGenerator.h" -#include "../Noise.h" +#include "../Noise/Noise.h" diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h index c9eb7de80..cc0fa87d9 100644 --- a/src/Generating/Trees.h +++ b/src/Generating/Trees.h @@ -18,7 +18,7 @@ logs can overwrite others(leaves), but others shouldn't overwrite logs. This is #pragma once #include "../ChunkDef.h" -#include "../Noise.h" +#include "../Noise/Noise.h" -- cgit v1.2.3 From c048f2bd95bd74c54f32e37978da47d450ac567b Mon Sep 17 00:00:00 2001 From: Mattes D Date: Tue, 18 Nov 2014 23:21:57 +0100 Subject: Added a cInterpolNoise template for faster noise generator. Used an instance of it in the Noise3D generator. --- src/Generating/Noise3DGenerator.cpp | 53 ++++++++++++++++++++++++++++++++++--- src/Generating/Noise3DGenerator.h | 5 +++- 2 files changed, 54 insertions(+), 4 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 654e9d01f..d051948c4 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "Noise3DGenerator.h" #include "../OSSupport/File.h" +#include "../OSSupport/Timer.h" #include "../IniFile.h" #include "../LinearInterpolation.h" #include "../LinearUpscale.h" @@ -61,6 +62,50 @@ public: +#if 0 +// Perform speed test of the cInterpolNoise class +static class cInterpolNoiseSpeedTest +{ +public: + cInterpolNoiseSpeedTest(void) + { + printf("Evaluating 3D noise performance...\n"); + static const int SIZE_X = 128; + static const int SIZE_Y = 128; + static const int SIZE_Z = 128; + static const NOISE_DATATYPE MUL = 80; + std::unique_ptr arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]); + cTimer timer; + + // Test the cInterpolNoise: + cInterpolNoise interpNoise(1); + long long start = timer.GetNowTime(); + for (int i = 0; i < 30; i++) + { + interpNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL); + } + long long end = timer.GetNowTime(); + printf("InterpolNoise took %.02f sec\n", static_cast(end - start) / 1000); + + // Test the cCubicNoise: + cCubicNoise cubicNoise(1); + start = timer.GetNowTime(); + for (int i = 0; i < 30; i++) + { + cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL); + } + end = timer.GetNowTime(); + printf("CubicNoise took %.02f sec\n", static_cast(end - start) / 1000); + printf("3D noise performance comparison finished.\n"); + } + +} g_InterpolNoiseSpeedTest; +#endif + + + + + //////////////////////////////////////////////////////////////////////////////// // cNoise3DGenerator: @@ -69,9 +114,11 @@ cNoise3DGenerator::cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator) : m_Perlin(1000), m_Cubic(1000) { - m_Perlin.AddOctave(1, (NOISE_DATATYPE)0.5); - m_Perlin.AddOctave((NOISE_DATATYPE)0.5, 1); - m_Perlin.AddOctave((NOISE_DATATYPE)0.5, 2); + m_Perlin.AddOctave(1, 1); + m_Perlin.AddOctave(2, 0.5); + m_Perlin.AddOctave(4, 0.25); + m_Perlin.AddOctave(8, 0.125); + m_Perlin.AddOctave(16, 0.0625); #if 0 // DEBUG: Test the noise generation: diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 8a6e97e1c..d198c5498 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -14,6 +14,7 @@ #include "ComposableGenerator.h" #include "../Noise/Noise.h" +#include "../Noise/InterpolNoise.h" @@ -43,7 +44,9 @@ protected: static const int DIM_Y = 1 + cChunkDef::Height / UPSCALE_Y; static const int DIM_Z = 1 + cChunkDef::Width / UPSCALE_Z; - cPerlinNoise m_Perlin; // The base 3D noise source for the actual composition + /** The base 3D noise source for the actual composition */ + cOctavedNoise m_Perlin; + cCubicNoise m_Cubic; // The noise used for heightmap directing int m_SeaLevel; -- cgit v1.2.3 From fef4133f6d7a3bbd08cba15034d0004aa1a76753 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 19 Nov 2014 16:58:27 +0100 Subject: cInterpolNoise: Implemented optimized 2D generating. --- src/Generating/Noise3DGenerator.cpp | 61 ++++++++++++++++++++++++++++++++----- src/Generating/Noise3DGenerator.h | 3 +- 2 files changed, 56 insertions(+), 8 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index d051948c4..78b739d32 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -68,6 +68,15 @@ static class cInterpolNoiseSpeedTest { public: cInterpolNoiseSpeedTest(void) + { + TestSpeed2D(); + TestSpeed3D(); + printf("InterpolNoise speed comparison finished.\n"); + } + + + /** Compare the speed of the 3D InterpolNoise vs 3D CubicNoise. */ + void TestSpeed3D(void) { printf("Evaluating 3D noise performance...\n"); static const int SIZE_X = 128; @@ -99,6 +108,38 @@ public: printf("3D noise performance comparison finished.\n"); } + + /** Compare the speed of the 2D InterpolNoise vs 2D CubicNoise. */ + void TestSpeed2D(void) + { + printf("Evaluating 2D noise performance...\n"); + static const int SIZE_X = 128; + static const int SIZE_Y = 128; + static const NOISE_DATATYPE MUL = 80; + std::unique_ptr arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y]); + cTimer timer; + + // Test the cInterpolNoise: + cInterpolNoise interpNoise(1); + long long start = timer.GetNowTime(); + for (int i = 0; i < 500; i++) + { + interpNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL); + } + long long end = timer.GetNowTime(); + printf("InterpolNoise took %.02f sec\n", static_cast(end - start) / 1000); + + // Test the cCubicNoise: + cCubicNoise cubicNoise(1); + start = timer.GetNowTime(); + for (int i = 0; i < 500; i++) + { + cubicNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL); + } + end = timer.GetNowTime(); + printf("CubicNoise took %.02f sec\n", static_cast(end - start) / 1000); + printf("2D noise performance comparison finished.\n"); + } } g_InterpolNoiseSpeedTest; #endif @@ -120,6 +161,12 @@ cNoise3DGenerator::cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator) : m_Perlin.AddOctave(8, 0.125); m_Perlin.AddOctave(16, 0.0625); + m_Cubic.AddOctave(1, 1); + m_Cubic.AddOctave(2, 0.5); + m_Cubic.AddOctave(4, 0.25); + m_Cubic.AddOctave(8, 0.125); + m_Cubic.AddOctave(16, 0.0625); + #if 0 // DEBUG: Test the noise generation: // NOTE: In order to be able to run MCS with this code, you need to increase the default thread stack size @@ -201,8 +248,8 @@ void cNoise3DGenerator::Initialize(cIniFile & a_IniFile) { // Params: m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62); - m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0); - m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75); + m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.1); + m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 68); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 8); m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 8); m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 8); @@ -280,23 +327,23 @@ void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DAT // Precalculate a "height" array: NOISE_DATATYPE Height[DIM_X * DIM_Z]; // Output for the cubic noise heightmap ("source") - m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 25, EndX / 25, StartZ / 25, EndZ / 25); + m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 5, EndX / 5, StartZ / 5, EndZ / 5); for (size_t i = 0; i < ARRAYCOUNT(Height); i++) { - Height[i] = std::abs(Height[i]) * m_HeightAmplification + 1; + Height[i] = Height[i] * m_HeightAmplification; } // Modify the noise by height data: for (int y = 0; y < DIM_Y; y++) { - NOISE_DATATYPE AddHeight = (y * UPSCALE_Y - m_MidPoint) / 20; - AddHeight *= AddHeight * AddHeight; + NOISE_DATATYPE AddHeight = (y * UPSCALE_Y - m_MidPoint) / 30; + // AddHeight *= AddHeight * AddHeight; for (int z = 0; z < DIM_Z; z++) { NOISE_DATATYPE * CurRow = &(NoiseO[y * DIM_X + z * DIM_X * DIM_Y]); for (int x = 0; x < DIM_X; x++) { - CurRow[x] += AddHeight / Height[x + DIM_X * z]; + CurRow[x] += AddHeight + Height[x + DIM_X * z]; } } } diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index d198c5498..07767ba84 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -47,7 +47,8 @@ protected: /** The base 3D noise source for the actual composition */ cOctavedNoise m_Perlin; - cCubicNoise m_Cubic; // The noise used for heightmap directing + /** The noise used for heightmap directing. */ + cOctavedNoise m_Cubic; int m_SeaLevel; NOISE_DATATYPE m_HeightAmplification; -- cgit v1.2.3 From 5325885ef49c57ecc7d7f071fc29df6c55467eb5 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 20 Nov 2014 14:45:20 +0100 Subject: Noise3D generators: Changed noise generator to InterpolNoise. --- src/Generating/CompoGenBiomal.cpp | 2 +- src/Generating/Noise3DGenerator.h | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp index 0bb7f4802..38c91c0d2 100644 --- a/src/Generating/CompoGenBiomal.cpp +++ b/src/Generating/CompoGenBiomal.cpp @@ -6,7 +6,7 @@ #include "Globals.h" #include "ComposableGenerator.h" #include "../IniFile.h" -#include "../Noise.h" +#include "../Noise/Noise.h" #include "../LinearUpscale.h" diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 7822a9efa..54429b42b 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -81,17 +81,17 @@ public: void Initialize(cIniFile & a_IniFile); protected: - /** The noise that is used to choose between density noise A and B. */ - cPerlinNoise m_ChoiceNoise; + /** The 3D noise that is used to choose between density noise A and B. */ + cOctavedNoise> m_ChoiceNoise; /** Density 3D noise, variant A. */ - cPerlinNoise m_DensityNoiseA; + cOctavedNoise> m_DensityNoiseA; /** Density 3D noise, variant B. */ - cPerlinNoise m_DensityNoiseB; + cOctavedNoise> m_DensityNoiseB; /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ - cPerlinNoise m_BaseNoise; + cOctavedNoise> m_BaseNoise; /** Block height of the sealevel, used for composing the terrain. */ int m_SeaLevel; @@ -155,16 +155,16 @@ protected: /** The noise that is used to choose between density noise A and B. */ - cPerlinNoise m_ChoiceNoise; + cOctavedNoise> m_ChoiceNoise; /** Density 3D noise, variant A. */ - cPerlinNoise m_DensityNoiseA; + cOctavedNoise> m_DensityNoiseA; /** Density 3D noise, variant B. */ - cPerlinNoise m_DensityNoiseB; + cOctavedNoise> m_DensityNoiseB; /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ - cPerlinNoise m_BaseNoise; + cOctavedNoise> m_BaseNoise; /** The underlying biome generator. */ cBiomeGenPtr m_BiomeGen; -- cgit v1.2.3 From 76058e81833b3b7df1c6d85d199e05abde4e8244 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 20 Nov 2014 15:31:03 +0100 Subject: Generators: Unified SeaLevel into a single variable. It is shared between shape generators and composition generators and there's no sense in having two different values for those. --- src/Generating/CompoGen.cpp | 2 +- src/Generating/Noise3DGenerator.cpp | 68 ++----------------------------------- src/Generating/Noise3DGenerator.h | 3 -- 3 files changed, 3 insertions(+), 70 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index db43e34b6..23cc64d78 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -197,7 +197,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc void cCompoGenClassic::InitializeCompoGen(cIniFile & a_IniFile) { - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "ClassicSeaLevel", m_SeaLevel); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel); m_BeachHeight = a_IniFile.GetValueSetI("Generator", "ClassicBeachHeight", m_BeachHeight); m_BeachDepth = a_IniFile.GetValueSetI("Generator", "ClassicBeachDepth", m_BeachDepth); m_BlockTop = (BLOCKTYPE)(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockTop", "grass").m_ItemType); diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 70844e6fa..4180693e0 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -166,69 +166,6 @@ cNoise3DGenerator::cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator) : m_Cubic.AddOctave(4, 0.25); m_Cubic.AddOctave(8, 0.125); m_Cubic.AddOctave(16, 0.0625); - - #if 0 - // DEBUG: Test the noise generation: - // NOTE: In order to be able to run MCS with this code, you need to increase the default thread stack size - // In MSVC, it is done in Project Settings -> Configuration Properties -> Linker -> System, set Stack reserve size to at least 64M - m_SeaLevel = 62; - m_HeightAmplification = 0; - m_MidPoint = 75; - m_FrequencyX = 4; - m_FrequencyY = 4; - m_FrequencyZ = 4; - m_AirThreshold = 0.5; - - const int NumChunks = 4; - NOISE_DATATYPE Noise[NumChunks][cChunkDef::Width * cChunkDef::Width * cChunkDef::Height]; - for (int x = 0; x < NumChunks; x++) - { - GenerateNoiseArray(x, 5, Noise[x]); - } - - // Save in XY cuts: - cFile f1; - if (f1.Open("Test_XY.grab", cFile::fmWrite)) - { - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int y = 0; y < cChunkDef::Height; y++) - { - for (int i = 0; i < NumChunks; i++) - { - int idx = y * cChunkDef::Width + z * cChunkDef::Width * cChunkDef::Height; - unsigned char buf[cChunkDef::Width]; - for (int x = 0; x < cChunkDef::Width; x++) - { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * Noise[i][idx++])))); - } - f1.Write(buf, cChunkDef::Width); - } - } // for y - } // for z - } // if (XY file open) - - cFile f2; - if (f2.Open("Test_XZ.grab", cFile::fmWrite)) - { - for (int y = 0; y < cChunkDef::Height; y++) - { - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int i = 0; i < NumChunks; i++) - { - int idx = y * cChunkDef::Width + z * cChunkDef::Width * cChunkDef::Height; - unsigned char buf[cChunkDef::Width]; - for (int x = 0; x < cChunkDef::Width; x++) - { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * Noise[i][idx++])))); - } - f2.Write(buf, cChunkDef::Width); - } - } // for z - } // for y - } // if (XZ file open) - #endif // 0 } @@ -247,7 +184,7 @@ cNoise3DGenerator::~cNoise3DGenerator() void cNoise3DGenerator::Initialize(cIniFile & a_IniFile) { // Params: - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.1); m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 68); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 8); @@ -455,7 +392,6 @@ void cNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: // The defaults generate extreme hills terrain - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62); m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.045); m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 40); @@ -608,7 +544,7 @@ void cBiomalNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: // The defaults generate extreme hills terrain - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DSeaLevel", 62); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyX", 40); m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyY", 40); m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyZ", 40); diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 54429b42b..1bc7f3fa1 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -93,9 +93,6 @@ protected: /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ cOctavedNoise> m_BaseNoise; - /** Block height of the sealevel, used for composing the terrain. */ - int m_SeaLevel; - /** 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; -- cgit v1.2.3 From 1e887d138103504e9a0df4ba5a601236ae608f98 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 20 Nov 2014 18:05:30 +0100 Subject: CompoGenBiomal: Fixed sealevel not generating properly. --- src/Generating/CompoGenBiomal.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp index 38c91c0d2..18bfa8b8c 100644 --- a/src/Generating/CompoGenBiomal.cpp +++ b/src/Generating/CompoGenBiomal.cpp @@ -427,7 +427,8 @@ protected: { bool HasHadWater = false; int PatternIdx = 0; - for (int y = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); y > 0; y--) + int top = std::max(m_SeaLevel, a_ChunkDesc.GetHeight(a_RelX, a_RelZ)); + for (int y = top; y > 0; y--) { if (a_ShapeColumn[y] > 0) { -- cgit v1.2.3 From b7dd2dddf941d85f348814b21e15907c535e8898 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 20 Nov 2014 22:45:50 +0100 Subject: CompoGenBiomal: Fixed sealevel offset. --- src/Generating/CompoGenBiomal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp index 18bfa8b8c..995851c95 100644 --- a/src/Generating/CompoGenBiomal.cpp +++ b/src/Generating/CompoGenBiomal.cpp @@ -221,7 +221,7 @@ protected: virtual void InitializeCompoGen(cIniFile & a_IniFile) override { - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel) - 1; + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel); } -- cgit v1.2.3 From 1ed32b825eee28b9cd1494ed5a010169619d3aa0 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 20 Nov 2014 22:48:14 +0100 Subject: BiomalNoise3D generator: finished all biomes. --- src/Generating/Noise3DGenerator.cpp | 140 +++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 66 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 4180693e0..fe6c9bdaf 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -481,6 +481,13 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) AddHeight *= 4; } + // If too high, cut off any terrain: + if (y > 28) + { + AddHeight = AddHeight + static_cast(y - 28) / 4; + } + + // Decide between the two density noises: int idx = 33 * x + 33 * 5 * z + y; Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } @@ -638,7 +645,13 @@ void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_Ch { AddHeight *= 4; } + // If too high, cut off any terrain: + if (y > 28) + { + AddHeight = AddHeight + static_cast(y - 28) / 4; + } + // Decide between the two density noises: int idx = 33 * x + y + 33 * 5 * z; Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } @@ -702,72 +715,67 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE { switch (a_Biome) { - case biBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; - case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; - case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break; - case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; - case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; - case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; - case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; - case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; - case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; - case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biMushroomShore: a_HeightAmp = 0.15f; a_MidPoint = 15; break; - case biOcean: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; - case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; - case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; - case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - - /* - // Still missing: - case biColdTaiga: a_HeightAmp = 0.15f; a_MidPoint = 30; break; - case biColdTaigaHills: a_HeightAmp = 0.15f; a_MidPoint = 31; break; - case biColdTaigaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biDesertM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biExtremeHillsEdge: a_HeightAmp = 0.15f; a_MidPoint = 20; break; - case biExtremeHillsM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biExtremeHillsPlusM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 23; break; - case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMegaSpruceTaiga: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMegaTaiga: a_HeightAmp = 0.15f; a_MidPoint = 32; break; - case biMesa: a_HeightAmp = 0.15f; a_MidPoint = 37; break; - case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMesaPlateau: a_HeightAmp = 0.15f; a_MidPoint = 39; break; - case biMesaPlateauF: a_HeightAmp = 0.15f; a_MidPoint = 38; break; - case biMesaPlateauFM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMesaPlateauM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMushroomIsland: a_HeightAmp = 0.15f; a_MidPoint = 14; break; - case biNether: a_HeightAmp = 0.15f; a_MidPoint = 68; break; - case biRoofedForest: a_HeightAmp = 0.15f; a_MidPoint = 29; break; - case biRoofedForestM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biSavanna: a_HeightAmp = 0.15f; a_MidPoint = 35; break; - case biSavannaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biSavannaPlateau: a_HeightAmp = 0.15f; a_MidPoint = 36; break; - case biSavannaPlateauM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biStoneBeach: a_HeightAmp = 0.15f; a_MidPoint = 25; break; - case biSunflowerPlains: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biTaiga: a_HeightAmp = 0.15f; a_MidPoint = 65; break; - case biTaigaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - */ - + case biBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biColdTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; + case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; + case biDesertM: a_HeightAmp = 0.29f; a_MidPoint = 62; break; + case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break; + case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biExtremeHillsEdge: a_HeightAmp = 0.1f; a_MidPoint = 70; break; + case biExtremeHillsM: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; + case biExtremeHillsPlusM: a_HeightAmp = 0.04f; a_MidPoint = 80; break; + case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 57; break; + case biFrozenOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; + case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 62; break; + case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 62; break; + case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biMegaSpruceTaiga: a_HeightAmp = 0.09f; a_MidPoint = 64; break; + case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biMegaTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biMesa: a_HeightAmp = 0.09f; a_MidPoint = 61; break; + case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 61; break; + case biMesaPlateau: a_HeightAmp = 0.25f; a_MidPoint = 86; break; + case biMesaPlateauF: a_HeightAmp = 0.25f; a_MidPoint = 96; break; + case biMesaPlateauFM: a_HeightAmp = 0.25f; a_MidPoint = 96; break; + case biMesaPlateauM: a_HeightAmp = 0.25f; a_MidPoint = 86; break; + case biMushroomShore: a_HeightAmp = 0.075f; a_MidPoint = 60; break; + case biMushroomIsland: a_HeightAmp = 0.06f; a_MidPoint = 80; break; + case biNether: a_HeightAmp = 0.01f; a_MidPoint = 64; break; + case biOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; + case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 57; break; + case biRoofedForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biRoofedForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biSavanna: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biSavannaM: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biSavannaPlateau: a_HeightAmp = 0.3f; a_MidPoint = 85; break; + case biSavannaPlateauM: a_HeightAmp = 0.012f; a_MidPoint = 105; break; + case biStoneBeach: a_HeightAmp = 0.075f; a_MidPoint = 60; break; + case biSunflowerPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; + case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; + case biTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 70; break; + case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; default: { // Make a crazy terrain so that it stands out -- cgit v1.2.3 From 9f4342434b7a34d0a9523e68b3d13a9eeeb116ca Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 23 Nov 2014 15:10:55 +0100 Subject: Noise3D generator: Enlarged averaging to avoid steep beach slopes. --- src/Generating/Noise3DGenerator.cpp | 4 ++-- src/Generating/Noise3DGenerator.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index fe6c9bdaf..a7af87bac 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -537,7 +537,7 @@ cBiomalNoise3DComposable::cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_Bi { for (int x = 0; x <= AVERAGING_SIZE * 2; x++) { - m_Weight[z][x] = static_cast((5 - std::abs(5 - x)) + (5 - std::abs(5 - z))); + m_Weight[z][x] = static_cast((AVERAGING_SIZE - std::abs(AVERAGING_SIZE - x)) + (AVERAGING_SIZE - std::abs(AVERAGING_SIZE - z))); m_WeightSum += m_Weight[z][x]; } } @@ -715,7 +715,7 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE { switch (a_Biome) { - case biBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biBeach: a_HeightAmp = 0.2f; a_MidPoint = 60; break; case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 1bc7f3fa1..35b1e4c94 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -144,8 +144,8 @@ public: void Initialize(cIniFile & a_IniFile); protected: - /** Number of columns around the pixel to query for biomes for averaging. */ - static const int AVERAGING_SIZE = 5; + /** Number of columns around the pixel to query for biomes for averaging. Must be less than or equal to 16. */ + static const int AVERAGING_SIZE = 9; /** Type used for a single parameter across the entire (downscaled) chunk. */ typedef NOISE_DATATYPE ChunkParam[5 * 5]; -- cgit v1.2.3 From 2ae4d2a96abf705c48d3e9440f301d1f88a9722a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 23 Nov 2014 17:13:40 +0000 Subject: Removed unnecessary #includes --- src/Generating/Noise3DGenerator.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 78b739d32..c8f87ec8e 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -6,7 +6,6 @@ #include "Globals.h" #include "Noise3DGenerator.h" #include "../OSSupport/File.h" -#include "../OSSupport/Timer.h" #include "../IniFile.h" #include "../LinearInterpolation.h" #include "../LinearUpscale.h" -- cgit v1.2.3 From 478bbad5ede86ec9f89444bdd60471ab314bf65a Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 23 Nov 2014 18:16:20 +0100 Subject: Added TwoHeights shape generator. This is a faster shape generator that can generate overhangs and has biome awareness. --- src/Generating/CMakeLists.txt | 8 ++- src/Generating/HeiGen.h | 13 ++--- src/Generating/ShapeGen.cpp | 5 ++ src/Generating/TwoHeights.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++ src/Generating/TwoHeights.h | 23 ++++++++ 5 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 src/Generating/TwoHeights.cpp create mode 100644 src/Generating/TwoHeights.h (limited to 'src/Generating') diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index dcb4bb3a7..a28510d40 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -31,8 +31,10 @@ SET (SRCS StructGen.cpp TestRailsGen.cpp Trees.cpp + TwoHeights.cpp UnderwaterBaseGen.cpp - VillageGen.cpp) + VillageGen.cpp +) SET (HDRS BioGen.h @@ -65,8 +67,10 @@ SET (HDRS StructGen.h TestRailsGen.h Trees.h + TwoHeights.h UnderwaterBaseGen.h - VillageGen.h) + VillageGen.h +) if(NOT MSVC) add_library(Generating ${SRCS} ${HDRS}) diff --git a/src/Generating/HeiGen.h b/src/Generating/HeiGen.h index 9c99a9326..62bb227c6 100644 --- a/src/Generating/HeiGen.h +++ b/src/Generating/HeiGen.h @@ -170,7 +170,11 @@ public: m_BiomeGen(a_BiomeGen) { } - + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + virtual void InitializeHeightGen(cIniFile & a_IniFile) override; + protected: typedef cChunkDef::BiomeMap BiomeNeighbors[3][3]; @@ -187,11 +191,8 @@ protected: float m_BaseHeight; } ; static const sGenParam m_GenParam[256]; - - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; - + + NOISE_DATATYPE GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, int a_ChunkZ, const BiomeNeighbors & a_BiomeNeighbors); } ; diff --git a/src/Generating/ShapeGen.cpp b/src/Generating/ShapeGen.cpp index 750b34e10..45a9c3b93 100644 --- a/src/Generating/ShapeGen.cpp +++ b/src/Generating/ShapeGen.cpp @@ -9,6 +9,7 @@ #include "DistortedHeightmap.h" #include "EndGen.h" #include "Noise3DGenerator.h" +#include "TwoHeights.h" @@ -121,6 +122,10 @@ cTerrainShapeGenPtr cTerrainShapeGen::CreateShapeGen(cIniFile & a_IniFile, cBiom { res = std::make_shared(a_Seed); } + else if (NoCaseCompare(shapeGenName, "TwoHeights") == 0) + { + res = CreateShapeGenTwoHeights(a_Seed, a_BiomeGen); + } else { // No match found, force-set the default and retry diff --git a/src/Generating/TwoHeights.cpp b/src/Generating/TwoHeights.cpp new file mode 100644 index 000000000..e75c301de --- /dev/null +++ b/src/Generating/TwoHeights.cpp @@ -0,0 +1,121 @@ + +// TwoHeights.cpp + +// Implements the cTwoHeights class representing the terrain shape generator using two switched heightmaps + +#include "Globals.h" +#include "TwoHeights.h" +#include "../Noise/InterpolNoise.h" +#include "HeiGen.h" +#include "../LinearUpscale.h" +#include "../IniFile.h" + + + + + +class cTwoHeights: + public cTerrainShapeGen +{ + typedef cTerrainShapeGen super; +public: + cTwoHeights(int a_Seed, cBiomeGenPtr a_BiomeGen): + m_Seed(a_Seed), + m_Choice(a_Seed), + m_HeightA(a_Seed + 1, a_BiomeGen), + m_HeightB(a_Seed + 2, a_BiomeGen) + { + } + + + // cTerrainShapeGen override: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override + { + // Generate the two heightmaps: + cChunkDef::HeightMap heightsA; + cChunkDef::HeightMap heightsB; + m_HeightA.GenHeightMap(a_ChunkX, a_ChunkZ, heightsA); + m_HeightB.GenHeightMap(a_ChunkX, a_ChunkZ, heightsB); + + // Generate the choice noise: + NOISE_DATATYPE smallChoice[33 * 5 * 5]; + NOISE_DATATYPE workspace[33 * 5 * 5]; + NOISE_DATATYPE startX = 0; + NOISE_DATATYPE endX = 256 * m_FrequencyY; + NOISE_DATATYPE startY = a_ChunkX * cChunkDef::Width * m_FrequencyX; + NOISE_DATATYPE endY = (a_ChunkX * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyX; + NOISE_DATATYPE startZ = a_ChunkZ * cChunkDef::Width * m_FrequencyZ; + NOISE_DATATYPE endZ = (a_ChunkZ * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyZ; + m_Choice.Generate3D(smallChoice, 33, 5, 5, startX, endX, startY, endY, startZ, endZ, workspace); + NOISE_DATATYPE choice[257 * 17 * 17]; + LinearUpscale3DArray(smallChoice, 33, 5, 5, choice, 8, 4, 4); + + // Generate the shape: + int idxShape = 0; + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + int idxChoice = 257 * 17 * z + 257 * x; + NOISE_DATATYPE heightA = static_cast(cChunkDef::GetHeight(heightsA, x, z)); + NOISE_DATATYPE heightB = static_cast(cChunkDef::GetHeight(heightsB, x, z)); + for (int y = 0; y < cChunkDef::Height; y++) + { + int height = static_cast(ClampedLerp(heightA, heightB, choice[idxChoice++])); + a_Shape[idxShape++] = (y < height) ? 1 : 0; + } + } // for x + } // for z + } + + + virtual void InitializeShapeGen(cIniFile & a_IniFile) + { + m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyX", 40)); + m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyY", 40)); + m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyZ", 40)); + + // Initialize the two underlying height generators from an empty INI file: + cIniFile empty; + m_HeightA.InitializeHeightGen(empty); + m_HeightB.InitializeHeightGen(empty); + + // Add the choice octaves: + NOISE_DATATYPE freq = 0.001f; + NOISE_DATATYPE ampl = 1; + for (int i = 0; i < 4; i++) + { + m_Choice.AddOctave(freq, ampl); + freq = freq * 2; + ampl = ampl / 2; + } + } + +protected: + int m_Seed; + + /** The noise used to decide between the two heightmaps. */ + cOctavedNoise> m_Choice; + + /** The first height generator. */ + cHeiGenBiomal m_HeightA; + + /** The second height generator. */ + cHeiGenBiomal m_HeightB; + + /** The base frequencies for m_Choice in each of the world axis directions. */ + NOISE_DATATYPE m_FrequencyX, m_FrequencyY, m_FrequencyZ; +}; + + + + + +cTerrainShapeGenPtr CreateShapeGenTwoHeights(int a_Seed, cBiomeGenPtr a_BiomeGen) +{ + return std::make_shared(a_Seed, a_BiomeGen); +} + + + + diff --git a/src/Generating/TwoHeights.h b/src/Generating/TwoHeights.h new file mode 100644 index 000000000..353598011 --- /dev/null +++ b/src/Generating/TwoHeights.h @@ -0,0 +1,23 @@ + +// TwoHeights.h + +// Declares the function to create a new instance of the cTwoHeights terrain shape generator + + + + + +#pragma once + +#include "ComposableGenerator.h" + + + + +/** Creates and returns a new instance of the cTwoHeights terrain shape generator. +The instance must be Initialize()-d before it is used. */ +extern cTerrainShapeGenPtr CreateShapeGenTwoHeights(int a_Seed, cBiomeGenPtr a_BiomeGen); + + + + -- cgit v1.2.3 From 187bdab4fa90fbfa5b1979ea529dc9c0deac89d9 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 25 Nov 2014 23:03:33 +0000 Subject: Merge remote-tracking branch 'origin-master' into c++11 --- src/Generating/CMakeLists.txt | 12 +- src/Generating/ChunkDesc.cpp | 63 ++++ src/Generating/ChunkDesc.h | 25 +- src/Generating/CompoGen.cpp | 336 +----------------- src/Generating/CompoGen.h | 45 +-- src/Generating/CompoGenBiomal.cpp | 586 ++++++++++++++++++++++++++++++++ src/Generating/CompoGenBiomal.h | 21 ++ src/Generating/ComposableGenerator.cpp | 112 +++--- src/Generating/ComposableGenerator.h | 95 ++++-- src/Generating/CompositedHeiGen.h | 49 +++ src/Generating/DistortedHeightmap.cpp | 565 +----------------------------- src/Generating/DistortedHeightmap.h | 60 +--- src/Generating/DungeonRoomsFinisher.cpp | 25 +- src/Generating/DungeonRoomsFinisher.h | 8 +- src/Generating/EndGen.cpp | 44 +-- src/Generating/EndGen.h | 8 +- src/Generating/FinishGen.cpp | 2 +- src/Generating/HeiGen.cpp | 92 +++-- src/Generating/HeiGen.h | 98 ++++-- src/Generating/Noise3DGenerator.cpp | 407 +++++++--------------- src/Generating/Noise3DGenerator.h | 51 ++- src/Generating/ShapeGen.cpp | 145 ++++++++ src/Generating/StructGen.cpp | 36 +- src/Generating/StructGen.h | 33 +- src/Generating/TwoHeights.cpp | 121 +++++++ src/Generating/TwoHeights.h | 23 ++ src/Generating/VillageGen.cpp | 6 +- 27 files changed, 1554 insertions(+), 1514 deletions(-) create mode 100644 src/Generating/CompoGenBiomal.cpp create mode 100644 src/Generating/CompoGenBiomal.h create mode 100644 src/Generating/CompositedHeiGen.h create mode 100644 src/Generating/ShapeGen.cpp create mode 100644 src/Generating/TwoHeights.cpp create mode 100644 src/Generating/TwoHeights.h (limited to 'src/Generating') diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index 1a26bd0d5..a28510d40 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -10,6 +10,7 @@ SET (SRCS ChunkDesc.cpp ChunkGenerator.cpp CompoGen.cpp + CompoGenBiomal.cpp ComposableGenerator.cpp DistortedHeightmap.cpp DungeonRoomsFinisher.cpp @@ -30,8 +31,10 @@ SET (SRCS StructGen.cpp TestRailsGen.cpp Trees.cpp + TwoHeights.cpp UnderwaterBaseGen.cpp - VillageGen.cpp) + VillageGen.cpp +) SET (HDRS BioGen.h @@ -39,7 +42,9 @@ SET (HDRS ChunkDesc.h ChunkGenerator.h CompoGen.h + CompoGenBiomal.h ComposableGenerator.h + CompositedHeiGen.h DistortedHeightmap.h DungeonRoomsFinisher.h EndGen.h @@ -58,11 +63,14 @@ SET (HDRS RainbowRoadsGen.h Ravines.h RoughRavines.h + ShapeGen.cpp StructGen.h TestRailsGen.h Trees.h + TwoHeights.h UnderwaterBaseGen.h - VillageGen.h) + VillageGen.h +) if(NOT MSVC) add_library(Generating ${SRCS} ${HDRS}) diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index 042b688b7..4a5ac5a18 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -152,6 +152,52 @@ int cChunkDesc::GetHeight(int a_RelX, int a_RelZ) +void cChunkDesc::SetHeightFromShape(const Shape & a_Shape) +{ + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + for (int y = cChunkDef::Height - 1; y > 0; y--) + { + if (a_Shape[y + x * 256 + z * 16 * 256] != 0) + { + cChunkDef::SetHeight(m_HeightMap, x, z, y); + break; + } + } // for y + } // for x + } // for z +} + + + + + +void cChunkDesc::GetShapeFromHeight(Shape & a_Shape) const +{ + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + int height = cChunkDef::GetHeight(m_HeightMap, x, z); + for (int y = 0; y <= height; y++) + { + 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; + } // for y + } // for x + } // for z +} + + + + + void cChunkDesc::SetUseDefaultBiomes(bool a_bUseDefaultBiomes) { m_bUseDefaultBiomes = a_bUseDefaultBiomes; @@ -366,6 +412,23 @@ HEIGHTTYPE cChunkDesc::GetMaxHeight(void) const +HEIGHTTYPE cChunkDesc::GetMinHeight(void) const +{ + HEIGHTTYPE MinHeight = m_HeightMap[0]; + for (size_t i = 1; i < ARRAYCOUNT(m_HeightMap); i++) + { + if (m_HeightMap[i] < MinHeight) + { + MinHeight = m_HeightMap[i]; + } + } + return MinHeight; +} + + + + + void cChunkDesc::FillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index 570132790..480106fb5 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -29,10 +29,17 @@ class cChunkDesc { public: // tolua_end + + /** The datatype used to represent the entire chunk worth of shape. + 0 = air + 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(); @@ -57,10 +64,21 @@ public: EMCSBiome GetBiome(int a_RelX, int a_RelZ); // These operate on the heightmap, so they could get out of sync with the data - // Use UpdateHeightmap() to re-sync + // Use UpdateHeightmap() to re-calculate heightmap from the block data void SetHeight(int a_RelX, int a_RelZ, int a_Height); int GetHeight(int a_RelX, int a_RelZ); + // tolua_end + + /** Sets the heightmap to match the given shape data. + Note that this ignores overhangs; the method is mostly used by old composition generators. */ + void SetHeightFromShape(const Shape & a_Shape); + + /** Sets the shape in a_Shape to match the heightmap stored currently in m_HeightMap. */ + void GetShapeFromHeight(Shape & a_Shape) const; + + // tolua_begin + // Default generation: void SetUseDefaultBiomes(bool a_bUseDefaultBiomes); bool IsUsingDefaultBiomes(void) const; @@ -77,8 +95,11 @@ public: /** Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas */ void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ); - /** Returns the maximum height value in the heightmap */ + /** Returns the maximum height value in the heightmap. */ HEIGHTTYPE GetMaxHeight(void) const; + + /** 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( diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 29b831dfd..23cc64d78 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -21,8 +21,9 @@ //////////////////////////////////////////////////////////////////////////////// // cCompoGenSameBlock: -void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { + a_ChunkDesc.SetHeightFromShape(a_Shape); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { @@ -63,7 +64,7 @@ void cCompoGenSameBlock::InitializeCompoGen(cIniFile & a_IniFile) //////////////////////////////////////////////////////////////////////////////// // cCompoGenDebugBiomes: -void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { static BLOCKTYPE Blocks[] = { @@ -92,6 +93,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc) E_BLOCK_BEDROCK, } ; + a_ChunkDesc.SetHeightFromShape(a_Shape); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) @@ -131,7 +133,7 @@ cCompoGenClassic::cCompoGenClassic(void) : -void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { /* The classic composition means: - 1 layer of grass, 3 of dirt and the rest stone, if the height > sealevel + beachheight @@ -142,6 +144,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc) */ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); + a_ChunkDesc.SetHeightFromShape(a_Shape); // The patterns to use for different situations, must be same length! const BLOCKTYPE PatternGround[] = {m_BlockTop, m_BlockMiddle, m_BlockMiddle, m_BlockMiddle} ; @@ -194,7 +197,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc) void cCompoGenClassic::InitializeCompoGen(cIniFile & a_IniFile) { - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "ClassicSeaLevel", m_SeaLevel); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel); m_BeachHeight = a_IniFile.GetValueSetI("Generator", "ClassicBeachHeight", m_BeachHeight); m_BeachDepth = a_IniFile.GetValueSetI("Generator", "ClassicBeachDepth", m_BeachDepth); m_BlockTop = (BLOCKTYPE)(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockTop", "grass").m_ItemType); @@ -209,323 +212,6 @@ void cCompoGenClassic::InitializeCompoGen(cIniFile & a_IniFile) -//////////////////////////////////////////////////////////////////////////////// -// cCompoGenBiomal: - -void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - - int ChunkX = a_ChunkDesc.GetChunkX(); - int ChunkZ = a_ChunkDesc.GetChunkZ(); - - /* - _X 2013_04_22: - There's no point in generating the whole cubic noise at once, because the noise values are used in - only about 20 % of the cases, so the speed gained by precalculating is lost by precalculating too much data - */ - - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - int Height = a_ChunkDesc.GetHeight(x, z); - if (Height > m_SeaLevel) - { - 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: - { - 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()); - break; - } - case biMushroomIsland: - case biMushroomShore: - { - FillColumnMycelium(x, z, Height, a_ChunkDesc.GetBlockTypes()); - break; - } - default: - { - // TODO - ASSERT(!"CompoGenBiomal: Biome not implemented yet!"); - break; - } - } - } - else - { - switch (a_ChunkDesc.GetBiome(x, z)) - { - case biDesert: - case biBeach: - { - // Fill with water, sand, sandstone and stone - FillColumnWaterSand(x, z, Height, a_ChunkDesc.GetBlockTypes()); - break; - } - default: - { - // Fill with water, sand/dirt/clay mix and stone - if (m_Noise.CubicNoise2D(0.3f * (cChunkDef::Width * ChunkX + x), 0.3f * (cChunkDef::Width * ChunkZ + z)) < 0) - { - FillColumnWaterSand(x, z, Height, a_ChunkDesc.GetBlockTypes()); - } - else - { - FillColumnWaterDirt(x, z, Height, a_ChunkDesc.GetBlockTypes()); - } - break; - } - } // switch (biome) - a_ChunkDesc.SetHeight(x, z, m_SeaLevel + 1); - } // else (under water) - a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); - } // for x - } // for z -} - - - - - -void cCompoGenBiomal::InitializeCompoGen(cIniFile & a_IniFile) -{ - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "BiomalSeaLevel", m_SeaLevel) - 1; -} - - - - - -void cCompoGenBiomal::FillColumnGrass(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - BLOCKTYPE Pattern[] = - { - E_BLOCK_GRASS, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - } ; - 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::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[] = - { - E_BLOCK_SAND, - E_BLOCK_SAND, - E_BLOCK_SAND, - E_BLOCK_SANDSTONE, - } ; - 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::FillColumnMycelium (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - BLOCKTYPE Pattern[] = - { - E_BLOCK_MYCELIUM, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - } ; - 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::FillColumnWaterSand(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - FillColumnSand(a_RelX, a_RelZ, a_Height, a_BlockTypes); - for (int y = a_Height + 1; y <= m_SeaLevel + 1; y++) - { - cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); - } -} - - - - - -void cCompoGenBiomal::FillColumnWaterDirt(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes) -{ - // Dirt - BLOCKTYPE Pattern[] = - { - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - E_BLOCK_DIRT, - } ; - 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); - } - for (int y = a_Height + 1; y <= m_SeaLevel + 1; y++) - { - cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); - } -} - - - - - - -void cCompoGenBiomal::FillColumnPattern(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes, const BLOCKTYPE * a_Pattern, int a_PatternSize) -{ - for (int y = a_Height, idx = 0; (y >= 0) && (idx < a_PatternSize); y--, idx++) - { - cChunkDef::SetBlock(a_BlockTypes, a_RelX, y, a_RelZ, a_Pattern[idx]); - } -} - - - - - //////////////////////////////////////////////////////////////////////////////// // cCompoGenNether: @@ -540,7 +226,7 @@ cCompoGenNether::cCompoGenNether(int a_Seed) : -void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); @@ -696,7 +382,7 @@ cCompoGenCache::~cCompoGenCache() -void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { #ifdef _DEBUG if (((m_NumHits + m_NumMisses) % 1024) == 10) @@ -731,6 +417,7 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc) // 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; @@ -739,7 +426,7 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc) // Not in the cache: m_NumMisses++; - m_Underlying->ComposeTerrain(a_ChunkDesc); + m_Underlying->ComposeTerrain(a_ChunkDesc, a_Shape); // Insert it as the first item in the MRU order: int Idx = m_CacheOrder[m_CacheSize - 1]; @@ -750,6 +437,7 @@ void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc) m_CacheOrder[0] = Idx; memcpy(m_CacheData[Idx].m_BlockTypes, a_ChunkDesc.GetBlockTypes(), sizeof(a_ChunkDesc.GetBlockTypes())); memcpy(m_CacheData[Idx].m_BlockMetas, a_ChunkDesc.GetBlockMetasUncompressed(), sizeof(a_ChunkDesc.GetBlockMetasUncompressed())); + memcpy(m_CacheData[Idx].m_HeightMap, a_ChunkDesc.GetHeightMap(), sizeof(a_ChunkDesc.GetHeightMap())); m_CacheData[Idx].m_ChunkX = ChunkX; m_CacheData[Idx].m_ChunkZ = ChunkZ; } diff --git a/src/Generating/CompoGen.h b/src/Generating/CompoGen.h index c65a07fe8..3847688cd 100644 --- a/src/Generating/CompoGen.h +++ b/src/Generating/CompoGen.h @@ -38,7 +38,7 @@ protected: bool m_IsBedrocked; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; @@ -55,7 +55,7 @@ public: protected: // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; } ; @@ -81,7 +81,7 @@ protected: BLOCKTYPE m_BlockSea; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; @@ -89,40 +89,6 @@ protected: -class cCompoGenBiomal : - public cTerrainCompositionGen -{ -public: - cCompoGenBiomal(int a_Seed) : - m_Noise(a_Seed + 1000), - m_SeaLevel(62) - { - } - -protected: - - cNoise m_Noise; - int m_SeaLevel; - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - 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); - void FillColumnWaterDirt(int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes); - - void FillColumnPattern (int a_RelX, int a_RelZ, int a_Height, cChunkDef::BlockTypes & a_BlockTypes, const BLOCKTYPE * a_Pattern, int a_PatternSize); -} ; - - - - - class cCompoGenNether : public cTerrainCompositionGen { @@ -136,7 +102,7 @@ protected: int m_Threshold; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; @@ -153,7 +119,7 @@ public: ~cCompoGenCache(); // cTerrainCompositionGen override: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; protected: @@ -166,6 +132,7 @@ protected: int m_ChunkZ; cChunkDef::BlockTypes m_BlockTypes; 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 diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp new file mode 100644 index 000000000..995851c95 --- /dev/null +++ b/src/Generating/CompoGenBiomal.cpp @@ -0,0 +1,586 @@ + +// CompoGenBiomal.cpp + +// Implements the cCompoGenBiomal class representing the biome-aware composition generator + +#include "Globals.h" +#include "ComposableGenerator.h" +#include "../IniFile.h" +#include "../Noise/Noise.h" +#include "../LinearUpscale.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// 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 columns. */ +class cPattern +{ +public: + struct BlockInfo + { + BLOCKTYPE m_BlockType; + NIBBLETYPE m_BlockMeta; + }; + + cPattern(BlockInfo * 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 BlockInfo Stone = {E_BLOCK_STONE, 0}; + for (size_t i = a_Count; i < cChunkDef::Height; i++) + { + m_Pattern[i] = Stone; + } + } + + const BlockInfo * Get(void) const { return m_Pattern; } + +protected: + BlockInfo m_Pattern[cChunkDef::Height]; +} ; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// The arrays to use for the top block pattern definitions: + +static cPattern::BlockInfo 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 cPattern::BlockInfo tbSand[] = +{ + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SANDSTONE, 0}, +} ; + +static cPattern::BlockInfo 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 cPattern::BlockInfo 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 cPattern::BlockInfo 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 cPattern::BlockInfo tbMycelium[] = +{ + {E_BLOCK_MYCELIUM, 0}, + {E_BLOCK_DIRT, 0}, + {E_BLOCK_DIRT, 0}, + {E_BLOCK_DIRT, 0}, +} ; + +static cPattern::BlockInfo tbGravel[] = +{ + {E_BLOCK_GRAVEL, 0}, + {E_BLOCK_GRAVEL, 0}, + {E_BLOCK_GRAVEL, 0}, + {E_BLOCK_STONE, 0}, +} ; + +static cPattern::BlockInfo tbStone[] = +{ + {E_BLOCK_STONE, 0}, + {E_BLOCK_STONE, 0}, + {E_BLOCK_STONE, 0}, + {E_BLOCK_STONE, 0}, +} ; + + + +//////////////////////////////////////////////////////////////////////////////// +// Ocean floor pattern top-block definitions: + +static cPattern::BlockInfo tbOFSand[] = +{ + {E_BLOCK_SAND, 0}, + {E_BLOCK_SAND, 0}, + {E_BLOCK_SAND, 0}, + {E_BLOCK_SANDSTONE, 0} +} ; + +static cPattern::BlockInfo tbOFClay[] = +{ + { E_BLOCK_CLAY, 0}, + { E_BLOCK_CLAY, 0}, + { E_BLOCK_SAND, 0}, + { E_BLOCK_SAND, 0}, +} ; + +static cPattern::BlockInfo tbOFOrangeClay[] = +{ + { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, + { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, +} ; + + + + + + +//////////////////////////////////////////////////////////////////////////////// +// 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 patGravel (tbGravel, ARRAYCOUNT(tbGravel)); +static cPattern patStone (tbStone, ARRAYCOUNT(tbStone)); + +static cPattern patOFSand (tbOFSand, ARRAYCOUNT(tbOFSand)); +static cPattern patOFClay (tbOFClay, ARRAYCOUNT(tbOFClay)); +static cPattern patOFOrangeClay(tbOFOrangeClay, ARRAYCOUNT(tbOFOrangeClay)); + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cCompoGenBiomal: + +class cCompoGenBiomal : + public cTerrainCompositionGen +{ +public: + cCompoGenBiomal(int a_Seed) : + m_SeaLevel(62), + m_OceanFloorSelect(a_Seed + 1), + m_MesaFloor(a_Seed + 2) + { + initMesaPattern(a_Seed); + } + +protected: + /** The block height at which water is generated instead of air. */ + int 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; + + /** Noise used for the floor of the clay blocks in mesa biomes. */ + cNoise m_MesaFloor; + + + // cTerrainCompositionGen overrides: + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override + { + a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + ComposeColumn(a_ChunkDesc, x, z, &(a_Shape[x * 256 + z * 16 * 256])); + } // for x + } // for z + } + + + + virtual void InitializeCompoGen(cIniFile & a_IniFile) override + { + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel); + } + + + + /** Initializes the m_MesaPattern with a pattern based on the generator's seed. */ + void initMesaPattern(int a_Seed) + { + // In a loop, choose whether to use one, two or three 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 = ARRAYCOUNT(m_MesaPattern) - 1; + while (idx >= 0) + { + // A layer group of 1 - 2 color stained clay: + int rnd = patternNoise.IntNoise1DInt(idx) / 7; + int numLayers = (rnd % 2) + 1; + rnd /= 2; + for (int lay = 0; lay < numLayers; lay++) + { + int numBlocks = layerSizes[(rnd % ARRAYCOUNT(layerSizes))]; + NIBBLETYPE Color = allowedColors[(rnd / 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 + rnd /= 32; + for (int block = 0; block < numBlocks; block++, idx--) + { + m_MesaPattern[idx].m_BlockMeta = Color; + m_MesaPattern[idx].m_BlockType = E_BLOCK_STAINED_CLAY; + } // for block + } // for lay + + // A layer of hardened clay in between the layer group: + int numBlocks = (rnd % 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].m_BlockMeta = 0; + m_MesaPattern[idx].m_BlockType = E_BLOCK_HARDENED_CLAY; + } // for block + } // while (idx >= 0) + } + + + + /** 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, const Byte * a_ShapeColumn) + { + // 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 biForest: + case biTaiga: + case biSwampland: + case biRiver: + case biFrozenOcean: + case biFrozenRiver: + case biIcePlains: + case biIceMountains: + case biForestHills: + case biTaigaHills: + case biExtremeHillsEdge: + case biExtremeHillsPlus: + case biExtremeHills: + case biJungle: + case biJungleHills: + case biJungleEdge: + case biDeepOcean: + case biStoneBeach: + case biColdBeach: + case biBirchForest: + case biBirchForestHills: + case biRoofedForest: + case biColdTaiga: + case biColdTaigaHills: + case biSavanna: + case biSavannaPlateau: + case biSunflowerPlains: + case biFlowerForest: + case biTaigaM: + case biSwamplandM: + case biIcePlainsSpikes: + case biJungleM: + case biJungleEdgeM: + case biBirchForestM: + case biBirchForestHillsM: + case biRoofedForestM: + case biColdTaigaM: + case biSavannaM: + case biSavannaPlateauM: + { + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patGrass.Get(), a_ShapeColumn); + return; + } + + case biMegaTaiga: + case biMegaTaigaHills: + case biMegaSpruceTaiga: + case biMegaSpruceTaigaHills: + { + // Select the pattern to use - podzol, grass or grassless dirt: + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; + NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); + const cPattern::BlockInfo * Pattern = (Val < -0.9) ? patGrassLess.Get() : ((Val > 0) ? patPodzol.Get() : patGrass.Get()); + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); + return; + } + + case biDesertHills: + case biDesert: + case biDesertM: + case biBeach: + { + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patSand.Get(), a_ShapeColumn); + return; + } + + case biMushroomIsland: + case biMushroomShore: + { + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patMycelium.Get(), a_ShapeColumn); + 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, a_ShapeColumn); + return; + } + + case biExtremeHillsPlusM: + case biExtremeHillsM: + { + // Select the pattern to use - gravel, stone or grass: + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; + NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); + const cPattern::BlockInfo * Pattern = (Val < 0.0) ? patStone.Get() : patGrass.Get(); + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); + return; + } + default: + { + ASSERT(!"Unhandled biome"); + return; + } + } // switch (Biome) + } + + + + /** 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 cPattern::BlockInfo * a_Pattern, const Byte * a_ShapeColumn) + { + bool HasHadWater = false; + int PatternIdx = 0; + int top = std::max(m_SeaLevel, a_ChunkDesc.GetHeight(a_RelX, a_RelZ)); + for (int y = top; y > 0; y--) + { + if (a_ShapeColumn[y] > 0) + { + // "ground" part, use the pattern: + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[PatternIdx].m_BlockType, a_Pattern[PatternIdx].m_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: + if (a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean) + { + a_Pattern = patGravel.Get(); + } + else + { + a_Pattern = ChooseOceanFloorPattern(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); + } + HasHadWater = true; + } // for y + a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); + } + + + + /** Fills the specified column with mesa pattern, based on the column height */ + void FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const Byte * a_ShapeColumn) + { + // 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 with red sand floor: + FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patOFOrangeClay.Get(), a_ShapeColumn); + return; + } + + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * 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 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; + bool HasHadWater = false; + for (int y = Top; y > 0; y--) + { + if (a_ShapeColumn[y] > 0) + { + // "ground" part, use the pattern: + a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, Pattern[PatternIdx].m_BlockType, Pattern[PatternIdx].m_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_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); + HasHadWater = true; + } // for y + a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); + } + + + + /** 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) + { + // 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)(a_ChunkX * cChunkDef::Width + a_RelX)) / FrequencyX; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkZ * 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(); + } + } +} ; + + + + + +cTerrainCompositionGenPtr CreateCompoGenBiomal(int a_Seed) +{ + return std::make_shared(a_Seed); +} + + + diff --git a/src/Generating/CompoGenBiomal.h b/src/Generating/CompoGenBiomal.h new file mode 100644 index 000000000..a3a65d3dc --- /dev/null +++ b/src/Generating/CompoGenBiomal.h @@ -0,0 +1,21 @@ + +// CompoGenBiomal.h + + + + + +#pragma once + +#include "ComposableGenerator.h" + + + + + +/** Returns a new instance of the Biomal composition generator. */ +cTerrainCompositionGenPtr CreateCompoGenBiomal(int a_Seed); + + + + diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 5f46574c7..4192dfa72 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -17,6 +17,10 @@ #include "StructGen.h" #include "FinishGen.h" +#include "CompoGenBiomal.h" + +#include "CompositedHeiGen.h" + #include "Caves.h" #include "DistortedHeightmap.h" #include "DungeonRoomsFinisher.h" @@ -39,7 +43,7 @@ //////////////////////////////////////////////////////////////////////////////// // cTerrainCompositionGen: -cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed) +cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, int a_Seed) { AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", ""); if (CompoGenName.empty()) @@ -48,63 +52,52 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile CompoGenName = "Biomal"; } - cTerrainCompositionGen * res = nullptr; - if (NoCaseCompare(CompoGenName, "sameblock") == 0) + // Compositor list is alpha-sorted + cTerrainCompositionGenPtr res; + if (NoCaseCompare(CompoGenName, "Biomal") == 0) { - res = new cCompoGenSameBlock; + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0) + else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) { - res = new cCompoGenDebugBiomes; + // The composition that used to be provided with BiomalNoise3D is now provided by the Biomal compositor: + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "classic") == 0) + else if (NoCaseCompare(CompoGenName, "Classic") == 0) { - res = new cCompoGenClassic; + res = std::make_shared(); } - else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) + else if (NoCaseCompare(CompoGenName, "DebugBiomes") == 0) { - res = new cDistortedHeightmap(a_Seed, a_BiomeGen); + res = std::make_shared(); } - else if (NoCaseCompare(CompoGenName, "end") == 0) + else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) { - res = new cEndGen(a_Seed); + // The composition that used to be provided with DistortedHeightmap is now provided by the Biomal compositor: + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "nether") == 0) + else if (NoCaseCompare(CompoGenName, "End") == 0) { - res = new cCompoGenNether(a_Seed); + res = std::make_shared(a_Seed); } - else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) + else if (NoCaseCompare(CompoGenName, "Nether") == 0) { - res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen); + res = std::make_shared(a_Seed); } else if (NoCaseCompare(CompoGenName, "Noise3D") == 0) { - res = new cNoise3DComposable(a_Seed); + // The composition that used to be provided with Noise3D is now provided by the Biomal compositor: + res = CreateCompoGenBiomal(a_Seed); } - else if (NoCaseCompare(CompoGenName, "biomal") == 0) + else if (NoCaseCompare(CompoGenName, "SameBlock") == 0) { - res = new cCompoGenBiomal(a_Seed); - - /* - // Performance-testing: - LOGINFO("Measuring performance of cCompoGenBiomal..."); - clock_t BeginTick = clock(); - for (int x = 0; x < 500; x++) - { - cChunkDesc Desc(200 + x * 8, 200 + x * 8); - a_BiomeGen->GenBiomes(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetBiomeMap()); - a_HeightGen->GenHeightMap(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetHeightMap()); - res->ComposeTerrain(Desc); - } - clock_t Duration = clock() - BeginTick; - LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); - //*/ + res = std::make_shared(); } else { LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); - return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed); + return CreateCompositionGen(a_IniFile, a_BiomeGen, a_ShapeGen, a_Seed); } ASSERT(res != nullptr); @@ -124,7 +117,7 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) : super(a_ChunkGenerator), m_BiomeGen(), - m_HeightGen(), + m_ShapeGen(), m_CompositionGen() { } @@ -138,7 +131,7 @@ void cComposableGenerator::Initialize(cIniFile & a_IniFile) super::Initialize(a_IniFile); InitBiomeGen(a_IniFile); - InitHeightGen(a_IniFile); + InitShapeGen(a_IniFile); InitCompositionGen(a_IniFile); InitFinishGens(a_IniFile); } @@ -166,16 +159,22 @@ 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()) { - m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetHeightMap()); + m_ShapeGen->GenShape(a_ChunkX, a_ChunkZ, shape); + a_ChunkDesc.SetHeightFromShape(shape); + } + else + { + // Convert the heightmap in a_ChunkDesc into shape: + a_ChunkDesc.GetShapeFromHeight(shape); } bool ShouldUpdateHeightmap = false; if (a_ChunkDesc.IsUsingDefaultComposition()) { - m_CompositionGen->ComposeTerrain(a_ChunkDesc); - ShouldUpdateHeightmap = true; + m_CompositionGen->ComposeTerrain(a_ChunkDesc, shape); } if (a_ChunkDesc.IsUsingDefaultFinish()) @@ -234,13 +233,15 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile) -void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile) +void cComposableGenerator::InitShapeGen(cIniFile & a_IniFile) { bool CacheOffByDefault = false; - m_HeightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault); + m_ShapeGen = cTerrainShapeGen::CreateShapeGen(a_IniFile, m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault); + /* + // TODO // Add a cache, if requested: - int CacheSize = a_IniFile.GetValueSetI("Generator", "HeightGenCacheSize", CacheOffByDefault ? 0 : 64); + int CacheSize = a_IniFile.GetValueSetI("Generator", "ShapeGenCacheSize", CacheOffByDefault ? 0 : 64); if (CacheSize > 0) { if (CacheSize < 4) @@ -253,6 +254,7 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile) LOGD("Using a cache for Heightgen of size %d.", CacheSize); m_HeightGen = cTerrainHeightGenPtr(new cHeiGenCache(m_HeightGen, CacheSize)); } + */ } @@ -261,13 +263,19 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile) void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile) { - m_CompositionGen = cTerrainCompositionGen::CreateCompositionGen(a_IniFile, m_BiomeGen, *m_HeightGen, m_ChunkGenerator.GetSeed()); + 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); - if (CompoGenCacheSize > 1) + if (CompoGenCacheSize > 0) { - m_CompositionGen = cTerrainCompositionGenPtr(new cCompoGenCache(m_CompositionGen, 32)); + m_CompositionGen = std::make_shared(m_CompositionGen, CompoGenCacheSize); } + + // Create a cache of the composited heightmaps, so that finishers may use it: + m_CompositedHeightCache = std::make_shared(std::make_shared(m_ShapeGen, m_CompositionGen), 16, 24); + // 24 subcaches of depth 16 each = 96 KiB of RAM. Acceptable, for the amount of work this saves. } @@ -333,7 +341,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) int MaxSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMaxSize", 7); int MinSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMinSize", 5); AString HeightDistrib = a_IniFile.GetValueSet ("Generator", "DungeonRoomsHeightDistrib", "0, 0; 10, 10; 11, 500; 40, 500; 60, 40; 90, 1"); - m_FinishGens.push_back(cFinishGenPtr(new cDungeonRoomsFinisher(m_HeightGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib))); + m_FinishGens.push_back(cFinishGenPtr(new cDungeonRoomsFinisher(m_ShapeGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib))); } else if (NoCaseCompare(*itr, "Ice") == 0) { @@ -342,7 +350,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) else if (NoCaseCompare(*itr, "LavaLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10); - m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, m_HeightGen, Probability))); + m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, m_ShapeGen, Probability))); } else if (NoCaseCompare(*itr, "LavaSprings") == 0) { @@ -580,7 +588,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "Trees") == 0) { - m_FinishGens.push_back(cFinishGenPtr(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen))); + m_FinishGens.push_back(cFinishGenPtr(new cStructGenTrees(Seed, m_BiomeGen, m_ShapeGen, m_CompositionGen))); } else if (NoCaseCompare(*itr, "UnderwaterBases") == 0) { @@ -588,7 +596,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) int MaxOffset = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxOffset", 128); int MaxDepth = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxDepth", 7); int MaxSize = a_IniFile.GetValueSetI("Generator", "UnderwaterBaseMaxSize", 128); - m_FinishGens.push_back(cFinishGenPtr(new cUnderwaterBaseGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, m_BiomeGen))); + m_FinishGens.push_back(std::make_shared(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, m_BiomeGen)); } else if (NoCaseCompare(*itr, "Villages") == 0) { @@ -598,12 +606,12 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) int MaxSize = a_IniFile.GetValueSetI("Generator", "VillageMaxSize", 128); int MinDensity = a_IniFile.GetValueSetI("Generator", "VillageMinDensity", 50); int MaxDensity = a_IniFile.GetValueSetI("Generator", "VillageMaxDensity", 80); - m_FinishGens.push_back(cFinishGenPtr(new cVillageGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, m_BiomeGen, m_HeightGen))); + m_FinishGens.push_back(std::make_shared(Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, m_BiomeGen, m_CompositedHeightCache)); } else if (NoCaseCompare(*itr, "WaterLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25); - m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, m_HeightGen, Probability))); + m_FinishGens.push_back(cFinishGenPtr(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, m_ShapeGen, Probability))); } else if (NoCaseCompare(*itr, "WaterSprings") == 0) { diff --git a/src/Generating/ComposableGenerator.h b/src/Generating/ComposableGenerator.h index a091f8d53..86c30e090 100644 --- a/src/Generating/ComposableGenerator.h +++ b/src/Generating/ComposableGenerator.h @@ -26,20 +26,16 @@ See http://forum.mc-server.org/showthread.php?tid=409 for details. // Forward-declare the shared pointers to subgenerator classes: class cBiomeGen; +class cTerrainShapeGen; class cTerrainHeightGen; class cTerrainCompositionGen; class cFinishGen; typedef SharedPtr cBiomeGenPtr; +typedef SharedPtr cTerrainShapeGenPtr; typedef SharedPtr cTerrainHeightGenPtr; typedef SharedPtr cTerrainCompositionGenPtr; typedef SharedPtr cFinishGenPtr; -// fwd: Noise3DGenerator.h -class cNoise3DComposable; - -// fwd: DistortedHeightmap.h -class cDistortedHeightmap; - @@ -70,28 +66,54 @@ public: -/** The interface that a terrain height generator must implement -A terrain height generator takes chunk coords on input and outputs an array of terrain heights for that chunk. -The output array is sequenced in the same way as the BiomeGen's biome data. +/** The interface that a terrain shape generator must implement +A terrain shape generator takes chunk coords on input and outputs a 3D array of "shape" for that chunk. The shape here +represents the distinction between air and solid; there's no representation of Water since that is added by the +composition geenrator. +The output array is indexed [y + 256 * z + 16 * 256 * x], so that it's fast to later compose a single column of the terrain, +which is the dominant operation following the shape generation. The generator may request biome information from the underlying BiomeGen, it may even request information for -other chunks than the one it's currently generating (possibly neighbors - for averaging) +other chunks than the one it's currently generating (neighbors - for averaging) */ -class cTerrainHeightGen +class cTerrainShapeGen { public: - virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants + virtual ~cTerrainShapeGen() {} // Force a virtual destructor in descendants - /** Generates heightmap for the given chunk */ - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) = 0; + /** 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 InitializeHeightGen(cIniFile & a_IniFile) {} + virtual void InitializeShapeGen(cIniFile & a_IniFile) {} - /** Creates the correct TerrainHeightGen descendant based on the ini file settings and the seed provided. - a_BiomeGen is the underlying biome generator, some height generators may depend on it to generate more biomes + /** 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 - Implemented in HeiGen.cpp! + Implemented in ShapeGen.cpp! */ + static cTerrainShapeGenPtr CreateShapeGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault); +} ; + + + + + +/** The interface that is used to query terrain height from the shape generator. +Usually the structure generators require only the final heightmap, and generating the whole shape only to +consume the heightmap is wasteful, so this interface is used instead; it has a cache implemented over it so +that data is retained. */ +class cTerrainHeightGen +{ +public: + virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants + + /** Retrieves the heightmap for the specified chunk. */ + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) = 0; + + /** Initializes the generator, reading its parameters from the INI file. */ + virtual void InitializeHeightGen(cIniFile & a_IniFile) {} + + /** Creates a cTerrainHeightGen descendant based on the INI file settings. */ static cTerrainHeightGenPtr CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault); } ; @@ -109,16 +131,18 @@ class cTerrainCompositionGen public: virtual ~cTerrainCompositionGen() {} // Force a virtual destructor in descendants - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) = 0; + /** 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 to generate more biomes - a_HeightGen is the underlying height generator, some composition generators may depend on it providing additional values + 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 */ - static cTerrainCompositionGenPtr CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed); + static cTerrainCompositionGenPtr CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, int a_Seed); } ; @@ -128,7 +152,7 @@ public: /** The interface that a finisher must implement Finisher implements changes to the chunk after the rough terrain has been generated. Examples of finishers are trees, snow, ore, lilypads and others. -Note that a worldgenerator may contain multiple finishers. +Note that a worldgenerator may contain multiple finishers, chained one after another. Also note that previously we used to distinguish between a structuregen and a finisher; this distinction is no longer relevant, all structure generators are considered finishers now (#398) */ @@ -154,23 +178,34 @@ class cComposableGenerator : 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; virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override; protected: - // The generation composition: - cBiomeGenPtr m_BiomeGen; - cTerrainHeightGenPtr m_HeightGen; + // The generator's composition: + /** The biome generator. */ + cBiomeGenPtr m_BiomeGen; + + /** The terrain shape generator. */ + cTerrainShapeGenPtr m_ShapeGen; + + /** The terrain composition generator. */ cTerrainCompositionGenPtr m_CompositionGen; - cFinishGenList m_FinishGens; + + /** The cache for the heights of the composited terrain. */ + cTerrainHeightGenPtr m_CompositedHeightCache; + + /** The finisher generators, in the order in which they are applied. */ + cFinishGenList m_FinishGens; - /** Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly */ + /** Reads the BiomeGen settings from the ini and initializes m_BiomeGen accordingly */ void InitBiomeGen(cIniFile & a_IniFile); - /** Reads the HeightGen settings from the ini and initializes m_HeightGen accordingly */ - void InitHeightGen(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); diff --git a/src/Generating/CompositedHeiGen.h b/src/Generating/CompositedHeiGen.h new file mode 100644 index 000000000..fa33a7861 --- /dev/null +++ b/src/Generating/CompositedHeiGen.h @@ -0,0 +1,49 @@ + +// CompositedHeiGen.h + +// Declares the cCompositedHeiGen class representing a cTerrainHeightGen descendant that calculates heightmap of the composited terrain +// This is used to further cache heightmaps for chunks already generated for finishers that require only heightmap information + + + + + +#pragma once + +#include "ComposableGenerator.h" + + + + + +class cCompositedHeiGen: + public cTerrainHeightGen +{ +public: + cCompositedHeiGen(cTerrainShapeGenPtr a_ShapeGen, cTerrainCompositionGenPtr a_CompositionGen): + m_ShapeGen(a_ShapeGen), + m_CompositionGen(a_CompositionGen) + { + } + + + + // cTerrainheightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override + { + cChunkDesc::Shape shape; + m_ShapeGen->GenShape(a_ChunkX, a_ChunkZ, shape); + cChunkDesc desc(a_ChunkX, a_ChunkZ); + desc.SetHeightFromShape(shape); + m_CompositionGen->ComposeTerrain(desc, shape); + memcpy(a_HeightMap, desc.GetHeightMap(), sizeof(a_HeightMap)); + } + +protected: + cTerrainShapeGenPtr m_ShapeGen; + cTerrainCompositionGenPtr m_CompositionGen; +}; + + + + diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index d5bc6ab55..e1ed9b450 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -14,163 +14,6 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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}, -} ; - -static cDistortedHeightmap::sBlockInfo tbGravel[] = -{ - {E_BLOCK_GRAVEL, 0}, - {E_BLOCK_GRAVEL, 0}, - {E_BLOCK_GRAVEL, 0}, - {E_BLOCK_STONE, 0}, -} ; - -static cDistortedHeightmap::sBlockInfo tbStone[] = -{ - {E_BLOCK_STONE, 0}, - {E_BLOCK_STONE, 0}, - {E_BLOCK_STONE, 0}, - {E_BLOCK_STONE, 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 patGravel (tbGravel, ARRAYCOUNT(tbGravel)); -static cPattern patStone (tbStone, ARRAYCOUNT(tbStone)); - -static cPattern patOFSand (tbOFSand, ARRAYCOUNT(tbOFSand)); -static cPattern patOFClay (tbOFClay, ARRAYCOUNT(tbOFClay)); -static cPattern patOFRedSand(tbOFRedSand, ARRAYCOUNT(tbOFRedSand)); - - - - - //////////////////////////////////////////////////////////////////////////////// // cDistortedHeightmap: @@ -237,7 +80,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}, // 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: + // Release 1.7 biome variants: /* biSunflowerPlains */ { 1.0f, 1.0f}, // 129 /* biDesertM */ { 1.0f, 1.0f}, // 130 /* biExtremeHillsM */ {16.0f, 16.0f}, // 131 @@ -279,8 +122,6 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGenPtr 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(new cHeiGenBiomal(a_Seed, a_BiomeGen)), m_HeightGen(m_UnderlyingHeiGen, 64), @@ -293,8 +134,6 @@ cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGenPtr 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); } @@ -309,7 +148,7 @@ void cDistortedHeightmap::Initialize(cIniFile & a_IniFile) } // Read the params from the INI file: - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "DistortedHeightmapSeaLevel", 62); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyX", 10); m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyY", 10); m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyZ", 10); @@ -321,89 +160,6 @@ 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)) @@ -474,23 +230,17 @@ void cDistortedHeightmap::GenerateHeightArray(void) -void cDistortedHeightmap::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cDistortedHeightmap::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { PrepareState(a_ChunkX, a_ChunkZ); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - int NoiseArrayIdx = x + 17 * 257 * z; - cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel - 1); - for (int y = cChunkDef::Height - 1; y > m_SeaLevel - 1; y--) + int idx = x + 17 * 257 * z; + for (int y = 0; y < cChunkDef::Height; y++) { - int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y]; - if (y < HeightMapHeight) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } + a_Shape[y + x * 256 + z * 16 * 256] = (y < m_DistortedHeightmap[idx + y * 17]) ? 1 : 0; } // for y } // for x } // for z @@ -500,36 +250,7 @@ void cDistortedHeightmap::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::He -void cDistortedHeightmap::InitializeHeightGen(cIniFile & a_IniFile) -{ - Initialize(a_IniFile); -} - - - - - -void cDistortedHeightmap::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - // Prepare the internal state for generating this chunk: - PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - // Compose: - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - ComposeColumn(a_ChunkDesc, x, z); - } // for x - } // for z -} - - - - - -void cDistortedHeightmap::InitializeCompoGen(cIniFile & a_IniFile) +void cDistortedHeightmap::InitializeShapeGen(cIniFile & a_IniFile) { Initialize(a_IniFile); } @@ -654,275 +375,3 @@ 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 biForest: - case biTaiga: - case biSwampland: - case biRiver: - case biFrozenOcean: - case biFrozenRiver: - case biIcePlains: - case biIceMountains: - case biForestHills: - case biTaigaHills: - case biExtremeHillsEdge: - case biExtremeHillsPlus: - case biExtremeHills: - case biJungle: - case biJungleHills: - case biJungleEdge: - case biDeepOcean: - case biStoneBeach: - case biColdBeach: - case biBirchForest: - case biBirchForestHills: - case biRoofedForest: - case biColdTaiga: - case biColdTaigaHills: - case biSavanna: - case biSavannaPlateau: - case biSunflowerPlains: - case biFlowerForest: - case biTaigaM: - case biSwamplandM: - case biIcePlainsSpikes: - case biJungleM: - case biJungleEdgeM: - case biBirchForestM: - case biBirchForestHillsM: - case biRoofedForestM: - case biColdTaigaM: - 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; - } - - case biExtremeHillsPlusM: - case biExtremeHillsM: - { - // Select the pattern to use - gravel, stone or grass: - 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.0) ? patStone.Get() : patGrass.Get(); - FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern); - return; - } - default: - { - ASSERT(!"Unhandled biome"); - return; - } - } // switch (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 = a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean ? patGravel.Get() : 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 955e57a1e..79fc35542 100644 --- a/src/Generating/DistortedHeightmap.h +++ b/src/Generating/DistortedHeightmap.h @@ -23,17 +23,9 @@ class cDistortedHeightmap : - public cTerrainHeightGen, - public cTerrainCompositionGen + public cTerrainShapeGen { public: - /// Structure used for storing block patterns for columns - struct sBlockInfo - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - } ; - cDistortedHeightmap(int a_Seed, cBiomeGenPtr a_BiomeGen); protected: @@ -51,8 +43,6 @@ 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; @@ -70,9 +60,9 @@ protected: cTerrainHeightGenPtr m_UnderlyingHeiGen; /** Cache for m_UnderlyingHeiGen. */ - cHeiGenCache m_HeightGen; + cHeiGenCache m_HeightGen; - /// Heightmap for the current chunk, before distortion (from m_HeightGen). Used for optimization. + /** Heightmap for the current chunk, before distortion (from m_HeightGen). Used for optimization. */ cChunkDef::HeightMap m_CurChunkHeights; // Per-biome terrain generator parameters: @@ -87,54 +77,30 @@ protected: 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) + /** 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) + /** 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 + /** Generates the m_DistortedHeightmap array for the current chunk. */ void GenerateHeightArray(void); - /// Calculates the heightmap value (before distortion) at the specified (floating-point) coords + /** 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 + /** 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 + /** 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 + /** 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; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - virtual void InitializeCompoGen(cIniFile & a_IniFile) override; + // cTerrainShapeGen overrides: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override; + virtual void InitializeShapeGen(cIniFile & a_IniFile) override; } ; diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 3f328868d..7ab22c2c5 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -78,7 +78,8 @@ protected: - /** Decodes the position index along the room walls into a proper 2D position for a chest. */ + /** Decodes the position index along the room walls into a proper 2D position for a chest. + The Y coord of the returned vector specifies the chest's meta value*/ Vector3i DecodeChestCoords(int a_PosIdx, int a_SizeX, int a_SizeZ) { if (a_PosIdx < a_SizeX) @@ -258,9 +259,9 @@ protected: //////////////////////////////////////////////////////////////////////////////// // cDungeonRoomsFinisher: -cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainHeightGenPtr a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) : +cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainShapeGenPtr a_ShapeGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) : super(a_Seed + 100, a_GridSize, a_GridSize, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 1024), - m_HeightGen(a_HeightGen), + m_ShapeGen(a_ShapeGen), m_MaxHalfSize((a_MaxSize + 1) / 2), m_MinHalfSize((a_MinSize + 1) / 2), m_HeightProbability(cChunkDef::Height) @@ -293,13 +294,21 @@ cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int int ChunkX, ChunkZ; int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ; cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ); - cChunkDef::HeightMap HeightMap; - m_HeightGen->GenHeightMap(ChunkX, ChunkZ, HeightMap); - int Height = cChunkDef::GetHeight(HeightMap, RelX, RelZ); // Max room height at {a_OriginX, a_OriginZ} - Height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, Height - 5); + cChunkDesc::Shape shape; + m_ShapeGen->GenShape(ChunkX, ChunkZ, shape); + int height = 0; + int idx = RelX * 256 + RelZ * 16 * 256; + for (int y = 6; y < cChunkDef::Height; y++) + { + if (shape[idx + y] != 0) + { + continue; + } + height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, y - 5); + } // Create the dungeon room descriptor: - return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, Height, m_Noise)); + return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, height, m_Noise)); } diff --git a/src/Generating/DungeonRoomsFinisher.h b/src/Generating/DungeonRoomsFinisher.h index 09dd0448a..e5828f989 100644 --- a/src/Generating/DungeonRoomsFinisher.h +++ b/src/Generating/DungeonRoomsFinisher.h @@ -23,15 +23,15 @@ class cDungeonRoomsFinisher : public: /** Creates a new dungeon room finisher. - a_HeightGen is the underlying height generator, so that the rooms can always be placed under the terrain. + a_ShapeGen is the underlying terrain shape generator, so that the rooms can always be placed under the terrain. a_MaxSize and a_MinSize are the maximum and minimum sizes of the room's internal (air) area, in blocks across. a_HeightDistrib is the string defining the height distribution for the rooms (cProbabDistrib format). */ - cDungeonRoomsFinisher(cTerrainHeightGenPtr a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib); + cDungeonRoomsFinisher(cTerrainShapeGenPtr a_ShapeGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib); protected: - /** The height gen that is used for limiting the rooms' Y coords */ - cTerrainHeightGenPtr m_HeightGen; + /** The shape gen that is used for limiting the rooms' Y coords */ + cTerrainShapeGenPtr m_ShapeGen; /** Maximum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 3 (vanilla). */ int m_MaxHalfSize; diff --git a/src/Generating/EndGen.cpp b/src/Generating/EndGen.cpp index 0111d2fa3..89d6117bb 100644 --- a/src/Generating/EndGen.cpp +++ b/src/Generating/EndGen.cpp @@ -147,13 +147,14 @@ bool cEndGen::IsChunkOutsideRange(int a_ChunkX, int a_ChunkZ) -void cEndGen::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cEndGen::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { + // If the chunk is outside out range, fill the shape with zeroes: if (IsChunkOutsideRange(a_ChunkX, a_ChunkZ)) { - for (size_t i = 0; i < ARRAYCOUNT(a_HeightMap); i++) + for (size_t i = 0; i < ARRAYCOUNT(a_Shape); i++) { - a_HeightMap[i] = 0; + a_Shape[i] = 0; } return; } @@ -165,15 +166,14 @@ void cEndGen::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_ { for (int x = 0; x < cChunkDef::Width; x++) { - cChunkDef::SetHeight(a_HeightMap, x, z, MaxY); - for (int y = MaxY; y > 0; y--) + for (int y = 0; y < MaxY; y++) { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= 0) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } - } // for y + a_Shape[(x + 16 * z) * 256 + y] = (m_NoiseArray[y * 17 * 17 + z * 17 + z] > 0) ? 1 : 0; + } + for (int y = MaxY; y < cChunkDef::Height; y++) + { + a_Shape[(x + 16 * z) * 256 + y] = 0; + } } // for x } // for z } @@ -182,30 +182,18 @@ void cEndGen::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_ -void cEndGen::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cEndGen::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { - if (IsChunkOutsideRange(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ())) - { - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - return; - } - - PrepareState(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - int MaxY = std::min((int)(1.75 * m_IslandSizeY + 1), cChunkDef::Height - 1); + a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - for (int y = MaxY; y > 0; y--) + for (int y = 0; y < cChunkDef::Height; y++) { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= 0) - { - a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_END_STONE, 0); - } - else + if (a_Shape[(x + 16 * z) * 256 + y] != 0) { - a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_AIR, 0); + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_END_STONE); } } // for y } // for x diff --git a/src/Generating/EndGen.h b/src/Generating/EndGen.h index c2278c1e1..f9e3f6e53 100644 --- a/src/Generating/EndGen.h +++ b/src/Generating/EndGen.h @@ -17,7 +17,7 @@ class cEndGen : - public cTerrainHeightGen, + public cTerrainShapeGen, public cTerrainCompositionGen { public: @@ -59,10 +59,10 @@ protected: /// Returns true if the chunk is outside of the island's dimensions bool IsChunkOutsideRange(int a_ChunkX, int a_ChunkZ); - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + // cTerrainShapeGen overrides: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override; // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 42ecdf8a8..2ff3e7f67 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -411,7 +411,7 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc) case biFrozenOcean: { int Height = a_ChunkDesc.GetHeight(x, z); - if (cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z))) + if (cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z)) && (Height < cChunkDef::Height - 1)) { a_ChunkDesc.SetBlockType(x, Height + 1, z, E_BLOCK_SNOW); a_ChunkDesc.SetHeight(x, z, Height + 1); diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index 1d9f1e3aa..61d087c17 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -15,7 +15,6 @@ - //////////////////////////////////////////////////////////////////////////////// // cHeiGenFlat: @@ -133,15 +132,6 @@ void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap -void cHeiGenCache::InitializeHeightGen(cIniFile & a_IniFile) -{ - m_HeiGenToCache->InitializeHeightGen(a_IniFile); -} - - - - - bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height) { for (int i = 0; i < m_CacheSize; i++) @@ -159,6 +149,51 @@ bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_Rel +//////////////////////////////////////////////////////////////////////////////// +// cHeiGenMultiCache: + +cHeiGenMultiCache::cHeiGenMultiCache(cTerrainHeightGenPtr a_HeiGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches): + m_NumSubCaches(a_NumSubCaches) +{ + // Create the individual sub-caches: + m_SubCaches.reserve(a_NumSubCaches); + for (size_t i = 0; i < a_NumSubCaches; i++) + { + m_SubCaches.push_back(std::make_shared(a_HeiGenToCache, a_SubCacheSize)); + } +} + + + + + +void cHeiGenMultiCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +{ + // Get the subcache responsible for this chunk: + const size_t cacheIdx = ((size_t)a_ChunkX + m_CoeffZ * (size_t)a_ChunkZ) % m_NumSubCaches; + + // Ask the subcache: + m_SubCaches[cacheIdx]->GenHeightMap(a_ChunkX, a_ChunkZ, a_HeightMap); +} + + + + + +bool cHeiGenMultiCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height) +{ + // Get the subcache responsible for this chunk: + const size_t cacheIdx = ((size_t)a_ChunkX + m_CoeffZ * (size_t)a_ChunkZ) % m_NumSubCaches; + + // Ask the subcache: + return m_SubCaches[cacheIdx]->GetHeightAt(a_ChunkX, a_ChunkZ, a_RelX, a_RelZ, a_Height); +} + + + + + + //////////////////////////////////////////////////////////////////////////////// // cHeiGenClassic: @@ -750,43 +785,51 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB } a_CacheOffByDefault = false; - cTerrainHeightGen * res = nullptr; - if (NoCaseCompare(HeightGenName, "flat") == 0) + cTerrainHeightGenPtr res; + if (NoCaseCompare(HeightGenName, "Flat") == 0) { - res = new cHeiGenFlat; + res = std::make_shared(); a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data } else if (NoCaseCompare(HeightGenName, "classic") == 0) { - res = new cHeiGenClassic(a_Seed); + res = std::make_shared(a_Seed); } else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0) { - res = new cDistortedHeightmap(a_Seed, a_BiomeGen); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } else if (NoCaseCompare(HeightGenName, "End") == 0) { - res = new cEndGen(a_Seed); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } else if (NoCaseCompare(HeightGenName, "MinMax") == 0) { - res = new cHeiGenMinMax(a_Seed, a_BiomeGen); + res = std::make_shared(a_Seed, a_BiomeGen); } else if (NoCaseCompare(HeightGenName, "Mountains") == 0) { - res = new cHeiGenMountains(a_Seed); + res = std::make_shared(a_Seed); } else if (NoCaseCompare(HeightGenName, "BiomalNoise3D") == 0) { - res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } else if (NoCaseCompare(HeightGenName, "Noise3D") == 0) { - res = new cNoise3DComposable(a_Seed); + // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it + // Return an empty pointer, the caller will create the proper generator: + return cTerrainHeightGenPtr(); } - else if (NoCaseCompare(HeightGenName, "biomal") == 0) + else if (NoCaseCompare(HeightGenName, "Biomal") == 0) { - res = new cHeiGenBiomal(a_Seed, a_BiomeGen); + res = std::make_shared(a_Seed, a_BiomeGen); /* // Performance-testing: @@ -805,15 +848,14 @@ cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cB { // No match found, force-set the default and retry LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str()); - a_IniFile.DeleteValue("Generator", "HeightGen"); a_IniFile.SetValue("Generator", "HeightGen", "Biomal"); return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); } // Read the settings: res->InitializeHeightGen(a_IniFile); - - return cTerrainHeightGenPtr(res); + + return res; } diff --git a/src/Generating/HeiGen.h b/src/Generating/HeiGen.h index b3c9483fb..62bb227c6 100644 --- a/src/Generating/HeiGen.h +++ b/src/Generating/HeiGen.h @@ -2,10 +2,12 @@ // HeiGen.h /* -Interfaces to the various height generators: +Interfaces to the various height-based terrain shape generators: - cHeiGenFlat - cHeiGenClassic - cHeiGenBiomal + +Also implements the heightmap cache */ @@ -21,26 +23,7 @@ Interfaces to the various height generators: -class cHeiGenFlat : - public cTerrainHeightGen -{ -public: - cHeiGenFlat(void) : m_Height(5) {} - -protected: - - int m_Height; - - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; -} ; - - - - - -/// A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation +/** A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation */ class cHeiGenCache : public cTerrainHeightGen { @@ -50,15 +33,11 @@ public: // cTerrainHeightGen overrides: virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; - /// Retrieves height at the specified point in the cache, returns true if found, false if not found + /** 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: - - cTerrainHeightGenPtr m_HeiGenToCache; - struct sCacheData { int m_ChunkX; @@ -66,6 +45,9 @@ protected: 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 int m_CacheSize; int * m_CacheOrder; // MRU-ized order, indices into m_CacheData array @@ -81,6 +63,57 @@ protected: +/** Caches heightmaps in multiple underlying caches to improve the distribution and lower the chain length. */ +class cHeiGenMultiCache: + public cTerrainHeightGen +{ +public: + cHeiGenMultiCache(cTerrainHeightGenPtr a_HeightGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches); + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) 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: + typedef SharedPtr cHeiGenCachePtr; + typedef std::vector cHeiGenCachePtrs; + + + /** The coefficient used to turn Z coords into index (x + Coeff * z). */ + static const size_t m_CoeffZ = 5; + + /** Number of sub-caches, pulled out of m_SubCaches.size() for performance reasons. */ + size_t m_NumSubCaches; + + /** The individual sub-caches. */ + cHeiGenCachePtrs m_SubCaches; +}; + + + + + +class cHeiGenFlat : + public cTerrainHeightGen +{ +public: + cHeiGenFlat(void) : m_Height(5) {} + +protected: + + int m_Height; + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + virtual void InitializeHeightGen(cIniFile & a_IniFile) override; +} ; + + + + + class cHeiGenClassic : public cTerrainHeightGen { @@ -137,7 +170,11 @@ public: m_BiomeGen(a_BiomeGen) { } - + + // cTerrainHeightGen overrides: + virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; + virtual void InitializeHeightGen(cIniFile & a_IniFile) override; + protected: typedef cChunkDef::BiomeMap BiomeNeighbors[3][3]; @@ -154,11 +191,8 @@ protected: float m_BaseHeight; } ; static const sGenParam m_GenParam[256]; - - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override; - + + NOISE_DATATYPE GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, int a_ChunkZ, const BiomeNeighbors & a_BiomeNeighbors); } ; diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index c8f87ec8e..5cf46b873 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -165,69 +165,6 @@ cNoise3DGenerator::cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator) : m_Cubic.AddOctave(4, 0.25); m_Cubic.AddOctave(8, 0.125); m_Cubic.AddOctave(16, 0.0625); - - #if 0 - // DEBUG: Test the noise generation: - // NOTE: In order to be able to run MCS with this code, you need to increase the default thread stack size - // In MSVC, it is done in Project Settings -> Configuration Properties -> Linker -> System, set Stack reserve size to at least 64M - m_SeaLevel = 62; - m_HeightAmplification = 0; - m_MidPoint = 75; - m_FrequencyX = 4; - m_FrequencyY = 4; - m_FrequencyZ = 4; - m_AirThreshold = 0.5; - - const int NumChunks = 4; - NOISE_DATATYPE Noise[NumChunks][cChunkDef::Width * cChunkDef::Width * cChunkDef::Height]; - for (int x = 0; x < NumChunks; x++) - { - GenerateNoiseArray(x, 5, Noise[x]); - } - - // Save in XY cuts: - cFile f1; - if (f1.Open("Test_XY.grab", cFile::fmWrite)) - { - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int y = 0; y < cChunkDef::Height; y++) - { - for (int i = 0; i < NumChunks; i++) - { - int idx = y * cChunkDef::Width + z * cChunkDef::Width * cChunkDef::Height; - unsigned char buf[cChunkDef::Width]; - for (int x = 0; x < cChunkDef::Width; x++) - { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * Noise[i][idx++])))); - } - f1.Write(buf, cChunkDef::Width); - } - } // for y - } // for z - } // if (XY file open) - - cFile f2; - if (f2.Open("Test_XZ.grab", cFile::fmWrite)) - { - for (int y = 0; y < cChunkDef::Height; y++) - { - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int i = 0; i < NumChunks; i++) - { - int idx = y * cChunkDef::Width + z * cChunkDef::Width * cChunkDef::Height; - unsigned char buf[cChunkDef::Width]; - for (int x = 0; x < cChunkDef::Width; x++) - { - buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * Noise[i][idx++])))); - } - f2.Write(buf, cChunkDef::Width); - } - } // for z - } // for y - } // if (XZ file open) - #endif // 0 } @@ -246,7 +183,7 @@ cNoise3DGenerator::~cNoise3DGenerator() void cNoise3DGenerator::Initialize(cIniFile & a_IniFile) { // Params: - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.1); m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 68); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 8); @@ -454,7 +391,6 @@ void cNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: // The defaults generate extreme hills terrain - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62); m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.045); m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 40); @@ -522,110 +458,60 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ) NOISE_DATATYPE BaseNoise[5 * 5]; NOISE_DATATYPE BlockX = static_cast(a_ChunkX * cChunkDef::Width); NOISE_DATATYPE BlockZ = static_cast(a_ChunkZ * cChunkDef::Width); - // Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z": - m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace); - m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); - m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x": + m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace); + m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); + m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); // Calculate the final noise based on the partial noises: - for (int y = 0; y < 33; y++) + for (int z = 0; z < 5; z++) { - NOISE_DATATYPE AddHeight = (static_cast(y * 8) - m_MidPoint) * m_HeightAmplification; - - // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: - if (AddHeight < 0) - { - AddHeight *= 4; - } - - for (int z = 0; z < 5; z++) + for (int x = 0; x < 5; x++) { - for (int x = 0; x < 5; x++) + NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z]; + for (int y = 0; y < 33; y++) { - int idx = x + 5 * z + 5 * 5 * y; - Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z]; - } - } - } - LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); -} + NOISE_DATATYPE AddHeight = (static_cast(y * 8) - m_MidPoint) * m_HeightAmplification; + // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: + if (AddHeight < 0) + { + AddHeight *= 4; + } - - - -void cNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) -{ - GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); - - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel); - for (int y = cChunkDef::Height - 1; y > m_SeaLevel; y--) - { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= m_AirThreshold) + // If too high, cut off any terrain: + if (y > 28) { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; + AddHeight = AddHeight + static_cast(y - 28) / 4; } - } // for y - } // for x - } // for z + + // Decide between the two density noises: + int idx = 33 * x + 33 * 5 * z + y; + Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; + } + } + } + LinearUpscale3DArray(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4); } -void cNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) +void cNoise3DComposable::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { - GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); + GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); - // Make basic terrain composition: + // Translate the noise array into Shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - int LastAir = a_ChunkDesc.GetHeight(x, z) + 1; - bool HasHadWater = false; - for (int y = LastAir; y < m_SeaLevel; y++) + for (int y = 0; y < cChunkDef::Height; y++) { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); + a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1; } - for (int y = LastAir - 1; y > 0; y--) - { - if (m_NoiseArray[x + 17 * z + 17 * 17 * y] > m_AirThreshold) - { - // "air" part - LastAir = y; - if (y < m_SeaLevel) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); - HasHadWater = true; - } - continue; - } - // "ground" part: - if (LastAir - y > 4) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE); - continue; - } - if (HasHadWater) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND); - } - else - { - a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); - } - } // for y - a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); } // for x } // for z } @@ -650,7 +536,7 @@ cBiomalNoise3DComposable::cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_Bi { for (int x = 0; x <= AVERAGING_SIZE * 2; x++) { - m_Weight[z][x] = static_cast((5 - std::abs(5 - x)) + (5 - std::abs(5 - z))); + m_Weight[z][x] = static_cast((AVERAGING_SIZE - std::abs(AVERAGING_SIZE - x)) + (AVERAGING_SIZE - std::abs(AVERAGING_SIZE - z))); m_WeightSum += m_Weight[z][x]; } } @@ -664,7 +550,7 @@ void cBiomalNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: // The defaults generate extreme hills terrain - m_SeaLevel = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DSeaLevel", 62); + m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyX", 40); m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyY", 40); m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyZ", 40); @@ -735,34 +621,42 @@ void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_Ch NOISE_DATATYPE BaseNoise[5 * 5]; NOISE_DATATYPE BlockX = static_cast(a_ChunkX * cChunkDef::Width); NOISE_DATATYPE BlockZ = static_cast(a_ChunkZ * cChunkDef::Width); - // Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z": - m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace); - m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); - m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace); + // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x": + m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace); + m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); + m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); // Calculate the final noise based on the partial noises: - for (int y = 0; y < 33; y++) + for (int z = 0; z < 5; z++) { - NOISE_DATATYPE BlockHeight = static_cast(y * 8); - for (int z = 0; z < 5; z++) + for (int x = 0; x < 5; x++) { - for (int x = 0; x < 5; x++) + NOISE_DATATYPE curMidPoint = MidPoint[x + 5 * z]; + NOISE_DATATYPE curHeightAmp = HeightAmp[x + 5 * z]; + NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z]; + for (int y = 0; y < 33; y++) { - NOISE_DATATYPE AddHeight = (BlockHeight - MidPoint[x + 5 * z]) * HeightAmp[x + 5 * z]; + NOISE_DATATYPE AddHeight = (static_cast(y * 8) - curMidPoint) * curHeightAmp; // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: if (AddHeight < 0) { AddHeight *= 4; } + // If too high, cut off any terrain: + if (y > 28) + { + AddHeight = AddHeight + static_cast(y - 28) / 4; + } - int idx = x + 5 * z + 5 * 5 * y; - Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z]; + // Decide between the two density noises: + int idx = 33 * x + y + 33 * 5 * z; + Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } } } - LinearUpscale3DArray(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8); + LinearUpscale3DArray(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4); } @@ -820,72 +714,67 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE { switch (a_Biome) { - case biBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; - case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; - case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break; - case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; - case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; - case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; - case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; - case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break; - case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; - case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; - case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biMushroomShore: a_HeightAmp = 0.15f; a_MidPoint = 15; break; - case biOcean: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break; - case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; - case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; - case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - - /* - // Still missing: - case biColdTaiga: a_HeightAmp = 0.15f; a_MidPoint = 30; break; - case biColdTaigaHills: a_HeightAmp = 0.15f; a_MidPoint = 31; break; - case biColdTaigaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biDesertM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biExtremeHillsEdge: a_HeightAmp = 0.15f; a_MidPoint = 20; break; - case biExtremeHillsM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biExtremeHillsPlusM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 23; break; - case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMegaSpruceTaiga: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMegaTaiga: a_HeightAmp = 0.15f; a_MidPoint = 32; break; - case biMesa: a_HeightAmp = 0.15f; a_MidPoint = 37; break; - case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMesaPlateau: a_HeightAmp = 0.15f; a_MidPoint = 39; break; - case biMesaPlateauF: a_HeightAmp = 0.15f; a_MidPoint = 38; break; - case biMesaPlateauFM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMesaPlateauM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biMushroomIsland: a_HeightAmp = 0.15f; a_MidPoint = 14; break; - case biNether: a_HeightAmp = 0.15f; a_MidPoint = 68; break; - case biRoofedForest: a_HeightAmp = 0.15f; a_MidPoint = 29; break; - case biRoofedForestM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biSavanna: a_HeightAmp = 0.15f; a_MidPoint = 35; break; - case biSavannaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biSavannaPlateau: a_HeightAmp = 0.15f; a_MidPoint = 36; break; - case biSavannaPlateauM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biStoneBeach: a_HeightAmp = 0.15f; a_MidPoint = 25; break; - case biSunflowerPlains: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - case biTaiga: a_HeightAmp = 0.15f; a_MidPoint = 65; break; - case biTaigaM: a_HeightAmp = 0.15f; a_MidPoint = 70; break; - */ - + case biBeach: a_HeightAmp = 0.2f; a_MidPoint = 60; break; + case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biColdTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biColdTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; + case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; + case biDesertM: a_HeightAmp = 0.29f; a_MidPoint = 62; break; + case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break; + case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biExtremeHillsEdge: a_HeightAmp = 0.1f; a_MidPoint = 70; break; + case biExtremeHillsM: a_HeightAmp = 0.045f; a_MidPoint = 75; break; + case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; + case biExtremeHillsPlusM: a_HeightAmp = 0.04f; a_MidPoint = 80; break; + case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 57; break; + case biFrozenOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; + case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 62; break; + case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 62; break; + case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; + case biMegaSpruceTaiga: a_HeightAmp = 0.09f; a_MidPoint = 64; break; + case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biMegaTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; + case biMesa: a_HeightAmp = 0.09f; a_MidPoint = 61; break; + case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 61; break; + case biMesaPlateau: a_HeightAmp = 0.25f; a_MidPoint = 86; break; + case biMesaPlateauF: a_HeightAmp = 0.25f; a_MidPoint = 96; break; + case biMesaPlateauFM: a_HeightAmp = 0.25f; a_MidPoint = 96; break; + case biMesaPlateauM: a_HeightAmp = 0.25f; a_MidPoint = 86; break; + case biMushroomShore: a_HeightAmp = 0.075f; a_MidPoint = 60; break; + case biMushroomIsland: a_HeightAmp = 0.06f; a_MidPoint = 80; break; + case biNether: a_HeightAmp = 0.01f; a_MidPoint = 64; break; + case biOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; + case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 57; break; + case biRoofedForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biRoofedForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biSavanna: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biSavannaM: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biSavannaPlateau: a_HeightAmp = 0.3f; a_MidPoint = 85; break; + case biSavannaPlateauM: a_HeightAmp = 0.012f; a_MidPoint = 105; break; + case biStoneBeach: a_HeightAmp = 0.075f; a_MidPoint = 60; break; + case biSunflowerPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; + case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; + case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; + case biTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; + case biTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 70; break; + case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; default: { // Make a crazy terrain so that it stands out @@ -899,78 +788,19 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE - -void cBiomalNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) +void cBiomalNoise3DComposable::GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) { GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ); + // Translate the noise array into Shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { - cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel); - for (int y = cChunkDef::Height - 1; y > m_SeaLevel; y--) - { - if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= m_AirThreshold) - { - cChunkDef::SetHeight(a_HeightMap, x, z, y); - break; - } - } // for y - } // for x - } // for z -} - - - - - -void cBiomalNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) -{ - GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()); - - a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); - - // Make basic terrain composition: - for (int z = 0; z < cChunkDef::Width; z++) - { - for (int x = 0; x < cChunkDef::Width; x++) - { - int LastAir = a_ChunkDesc.GetHeight(x, z) + 1; - bool HasHadWater = false; - for (int y = LastAir; y < m_SeaLevel; y++) + for (int y = 0; y < cChunkDef::Height; y++) { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); + a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1; } - for (int y = LastAir - 1; y > 0; y--) - { - if (m_NoiseArray[x + 17 * z + 17 * 17 * y] > m_AirThreshold) - { - // "air" part - LastAir = y; - if (y < m_SeaLevel) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER); - HasHadWater = true; - } - continue; - } - // "ground" part: - if (LastAir - y > 4) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE); - continue; - } - if (HasHadWater) - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND); - } - else - { - a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); - } - } // for y - a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); } // for x } // for z } @@ -978,3 +808,4 @@ void cBiomalNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc) + diff --git a/src/Generating/Noise3DGenerator.h b/src/Generating/Noise3DGenerator.h index 07767ba84..35b1e4c94 100644 --- a/src/Generating/Noise3DGenerator.h +++ b/src/Generating/Noise3DGenerator.h @@ -73,8 +73,7 @@ protected: class cNoise3DComposable : - public cTerrainHeightGen, - public cTerrainCompositionGen + public cTerrainShapeGen { public: cNoise3DComposable(int a_Seed); @@ -82,21 +81,18 @@ public: void Initialize(cIniFile & a_IniFile); protected: - /** The noise that is used to choose between density noise A and B. */ - cPerlinNoise m_ChoiceNoise; + /** The 3D noise that is used to choose between density noise A and B. */ + cOctavedNoise> m_ChoiceNoise; /** Density 3D noise, variant A. */ - cPerlinNoise m_DensityNoiseA; + cOctavedNoise> m_DensityNoiseA; /** Density 3D noise, variant B. */ - cPerlinNoise m_DensityNoiseB; + cOctavedNoise> m_DensityNoiseB; /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ - cPerlinNoise m_BaseNoise; + cOctavedNoise> m_BaseNoise; - /** Block height of the sealevel, used for composing the terrain. */ - int m_SeaLevel; - /** 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; @@ -131,12 +127,8 @@ protected: void GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ); // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override; + virtual void InitializeShapeGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } } ; @@ -144,8 +136,7 @@ protected: class cBiomalNoise3DComposable : - public cTerrainHeightGen, - public cTerrainCompositionGen + public cTerrainShapeGen { public: cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_BiomeGen); @@ -153,24 +144,24 @@ public: void Initialize(cIniFile & a_IniFile); protected: - /** Number of columns around the pixel to query for biomes for averaging. */ - static const int AVERAGING_SIZE = 5; + /** Number of columns around the pixel to query for biomes for averaging. Must be less than or equal to 16. */ + static const int AVERAGING_SIZE = 9; /** Type used for a single parameter across the entire (downscaled) chunk. */ typedef NOISE_DATATYPE ChunkParam[5 * 5]; /** The noise that is used to choose between density noise A and B. */ - cPerlinNoise m_ChoiceNoise; + cOctavedNoise> m_ChoiceNoise; /** Density 3D noise, variant A. */ - cPerlinNoise m_DensityNoiseA; + cOctavedNoise> m_DensityNoiseA; /** Density 3D noise, variant B. */ - cPerlinNoise m_DensityNoiseB; + cOctavedNoise> m_DensityNoiseB; /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ - cPerlinNoise m_BaseNoise; + cOctavedNoise> m_BaseNoise; /** The underlying biome generator. */ cBiomeGenPtr m_BiomeGen; @@ -198,7 +189,7 @@ protected: // 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 + NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // 257 * x + y + 257 * 17 * z /** Weights for summing up neighboring biomes. */ NOISE_DATATYPE m_Weight[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1]; @@ -216,13 +207,9 @@ protected: /** Returns the parameters for the specified biome. */ void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint); - // cTerrainHeightGen overrides: - virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override; - virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } - - // cTerrainCompositionGen overrides: - virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; - virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(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 { Initialize(a_IniFile); } } ; diff --git a/src/Generating/ShapeGen.cpp b/src/Generating/ShapeGen.cpp new file mode 100644 index 000000000..45a9c3b93 --- /dev/null +++ b/src/Generating/ShapeGen.cpp @@ -0,0 +1,145 @@ + +// ShapeGen.cpp + +// Implements the function to create a cTerrainShapeGen descendant based on INI file settings + +#include "Globals.h" +#include "HeiGen.h" +#include "../IniFile.h" +#include "DistortedHeightmap.h" +#include "EndGen.h" +#include "Noise3DGenerator.h" +#include "TwoHeights.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cTerrainHeightToShapeGen: + +/** Converts old-style height-generators into new-style shape-generators. */ +class cTerrainHeightToShapeGen: + public cTerrainShapeGen +{ +public: + cTerrainHeightToShapeGen(cTerrainHeightGenPtr a_HeightGen): + m_HeightGen(a_HeightGen) + { + } + + + // cTerrainShapeGen overrides: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override + { + // Generate the heightmap: + cChunkDef::HeightMap heightMap; + m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, heightMap); + + // Convert from heightmap to shape: + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + HEIGHTTYPE height = cChunkDef::GetHeight(heightMap, x, z) + 1; + Byte * shapeColumn = &(a_Shape[(x + 16 * z) * 256]); + for (int y = 0; y < height; y++) + { + shapeColumn[y] = 1; + } + for (int y = height; y < cChunkDef::Height; y++) + { + shapeColumn[y] = 0; + } + } // for x + } // for z + } + + + virtual void InitializeShapeGen(cIniFile & a_IniFile) override + { + m_HeightGen->InitializeHeightGen(a_IniFile); + } + +protected: + /** The height generator being converted. */ + cTerrainHeightGenPtr m_HeightGen; +}; + +typedef SharedPtr cTerrainHeightToShapeGenPtr; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cTerrainShapeGen: + +cTerrainShapeGenPtr cTerrainShapeGen::CreateShapeGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault) +{ + AString shapeGenName = a_IniFile.GetValueSet("Generator", "ShapeGen", ""); + if (shapeGenName.empty()) + { + 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) + { + cTerrainHeightGenPtr heightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); + if (heightGen != nullptr) + { + return std::make_shared(heightGen); + } + + // The height gen was not recognized; several heightgens were promoted to shape gens, so let's try them instead: + shapeGenName = a_IniFile.GetValue("Generator", "HeightGen", ""); + if (shapeGenName.empty()) + { + LOGWARNING("[Generator] ShapeGen set to HeightMap, but HeightGen not set. Reverting to \"BiomalNoise3D\"."); + shapeGenName = "BiomalNoise3D"; + a_IniFile.SetValue("Generator", "ShapeGen", shapeGenName); + } + } + + // Choose the shape generator based on the name: + a_CacheOffByDefault = false; + cTerrainShapeGenPtr res; + if (NoCaseCompare(shapeGenName, "DistortedHeightmap") == 0) + { + res = std::make_shared(a_Seed, a_BiomeGen); + } + else if (NoCaseCompare(shapeGenName, "End") == 0) + { + res = std::make_shared(a_Seed); + } + else if (NoCaseCompare(shapeGenName, "BiomalNoise3D") == 0) + { + res = std::make_shared(a_Seed, a_BiomeGen); + } + else if (NoCaseCompare(shapeGenName, "Noise3D") == 0) + { + res = std::make_shared(a_Seed); + } + else if (NoCaseCompare(shapeGenName, "TwoHeights") == 0) + { + res = CreateShapeGenTwoHeights(a_Seed, a_BiomeGen); + } + else + { + // No match found, force-set the default and retry + LOGWARN("Unknown ShapeGen \"%s\", using \"BiomalNoise3D\" instead.", shapeGenName.c_str()); + 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; +} + + + + diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp index bdefcd8c1..2f685c808 100644 --- a/src/Generating/StructGen.cpp +++ b/src/Generating/StructGen.cpp @@ -37,10 +37,13 @@ void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc) 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; m_BiomeGen->GenBiomes (BaseX, BaseZ, WorkerDesc.GetBiomeMap()); - m_HeightGen->GenHeightMap (BaseX, BaseZ, WorkerDesc.GetHeightMap()); - m_CompositionGen->ComposeTerrain(WorkerDesc); - // TODO: Free the entity lists + m_ShapeGen->GenShape (BaseX, BaseZ, workerShape); + WorkerDesc.SetHeightFromShape (workerShape); + m_CompositionGen->ComposeTerrain(WorkerDesc, workerShape); } else { @@ -97,7 +100,7 @@ void cStructGenTrees::GenerateSingleTree( int Height = a_ChunkDesc.GetHeight(x, z); - if ((Height <= 0) || (Height > 240)) + if ((Height <= 0) || (Height >= 230)) { return; } @@ -125,6 +128,11 @@ void cStructGenTrees::GenerateSingleTree( // Outside the chunk continue; } + if (itr->y >= cChunkDef::Height) + { + // Above the chunk, cut off (this shouldn't happen too often, we're limiting trees to y < 230) + continue; + } BLOCKTYPE Block = a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z); switch (Block) @@ -159,7 +167,7 @@ void cStructGenTrees::ApplyTreeImage( // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks for (sSetBlockVector::const_iterator itr = a_Image.begin(), end = a_Image.end(); itr != end; ++itr) { - if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ)) + if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ) && (itr->y < cChunkDef::Height)) { // Inside this chunk, integrate into a_ChunkDesc: switch (a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z)) @@ -390,7 +398,7 @@ void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc) } cBlockArea Lake; - CreateLakeImage(ChunkX + x, ChunkZ + z, Lake); + CreateLakeImage(ChunkX + x, ChunkZ + z, a_ChunkDesc.GetMinHeight(), Lake); int OfsX = Lake.GetOriginX() + x * cChunkDef::Width; int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width; @@ -404,25 +412,13 @@ void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc) -void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake) +void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea & a_Lake) { a_Lake.Create(16, 8, 16); a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy - // Find the minimum height in this chunk: - cChunkDef::HeightMap HeightMap; - m_HeiGen->GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap); - HEIGHTTYPE MinHeight = HeightMap[0]; - for (size_t i = 1; i < ARRAYCOUNT(HeightMap); i++) - { - if (HeightMap[i] < MinHeight) - { - MinHeight = HeightMap[i]; - } - } - // 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 - MinHeight = std::max(MinHeight - 6, 2); + int MinHeight = std::max(a_MaxLakeHeight - 6, 2); int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11; // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8; diff --git a/src/Generating/StructGen.h b/src/Generating/StructGen.h index d3b0b5544..796abf0f5 100644 --- a/src/Generating/StructGen.h +++ b/src/Generating/StructGen.h @@ -24,11 +24,11 @@ class cStructGenTrees : public cFinishGen { public: - cStructGenTrees(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen, cTerrainCompositionGenPtr a_CompositionGen) : + cStructGenTrees(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, cTerrainCompositionGenPtr a_CompositionGen) : m_Seed(a_Seed), m_Noise(a_Seed), m_BiomeGen(a_BiomeGen), - m_HeightGen(a_HeightGen), + m_ShapeGen(a_ShapeGen), m_CompositionGen(a_CompositionGen) {} @@ -37,12 +37,12 @@ protected: int m_Seed; cNoise m_Noise; cBiomeGenPtr m_BiomeGen; - cTerrainHeightGenPtr m_HeightGen; + 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_BlockX. - Parts of the tree outside the chunk are stored in a_OutsideX + Parts of the tree inside the chunk are applied to a_ChunkDesc. + Parts of the tree outside the chunk are stored in a_OutsideXYZ */ void GenerateSingleTree( int a_ChunkX, int a_ChunkZ, int a_Seq, @@ -51,7 +51,7 @@ protected: sSetBlockVector & a_OutsideOther ) ; - /// Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow + /** 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, cChunkDesc & a_ChunkDesc, @@ -124,27 +124,30 @@ class cStructGenLakes : public cFinishGen { public: - cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainHeightGenPtr a_HeiGen, int a_Probability) : + cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainShapeGenPtr a_ShapeGen, int a_Probability) : m_Noise(a_Seed), m_Seed(a_Seed), m_Fluid(a_Fluid), - m_HeiGen(a_HeiGen), + m_ShapeGen(a_ShapeGen), m_Probability(a_Probability) { } protected: - cNoise m_Noise; - int m_Seed; - BLOCKTYPE m_Fluid; - cTerrainHeightGenPtr m_HeiGen; - int m_Probability; ///< Chance, 0 .. 100, of a chunk having the lake + cNoise m_Noise; + int m_Seed; + BLOCKTYPE m_Fluid; + cTerrainShapeGenPtr m_ShapeGen; + + /** 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, cBlockArea & a_Lake); + /** 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); } ; diff --git a/src/Generating/TwoHeights.cpp b/src/Generating/TwoHeights.cpp new file mode 100644 index 000000000..e75c301de --- /dev/null +++ b/src/Generating/TwoHeights.cpp @@ -0,0 +1,121 @@ + +// TwoHeights.cpp + +// Implements the cTwoHeights class representing the terrain shape generator using two switched heightmaps + +#include "Globals.h" +#include "TwoHeights.h" +#include "../Noise/InterpolNoise.h" +#include "HeiGen.h" +#include "../LinearUpscale.h" +#include "../IniFile.h" + + + + + +class cTwoHeights: + public cTerrainShapeGen +{ + typedef cTerrainShapeGen super; +public: + cTwoHeights(int a_Seed, cBiomeGenPtr a_BiomeGen): + m_Seed(a_Seed), + m_Choice(a_Seed), + m_HeightA(a_Seed + 1, a_BiomeGen), + m_HeightB(a_Seed + 2, a_BiomeGen) + { + } + + + // cTerrainShapeGen override: + virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override + { + // Generate the two heightmaps: + cChunkDef::HeightMap heightsA; + cChunkDef::HeightMap heightsB; + m_HeightA.GenHeightMap(a_ChunkX, a_ChunkZ, heightsA); + m_HeightB.GenHeightMap(a_ChunkX, a_ChunkZ, heightsB); + + // Generate the choice noise: + NOISE_DATATYPE smallChoice[33 * 5 * 5]; + NOISE_DATATYPE workspace[33 * 5 * 5]; + NOISE_DATATYPE startX = 0; + NOISE_DATATYPE endX = 256 * m_FrequencyY; + NOISE_DATATYPE startY = a_ChunkX * cChunkDef::Width * m_FrequencyX; + NOISE_DATATYPE endY = (a_ChunkX * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyX; + NOISE_DATATYPE startZ = a_ChunkZ * cChunkDef::Width * m_FrequencyZ; + NOISE_DATATYPE endZ = (a_ChunkZ * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyZ; + m_Choice.Generate3D(smallChoice, 33, 5, 5, startX, endX, startY, endY, startZ, endZ, workspace); + NOISE_DATATYPE choice[257 * 17 * 17]; + LinearUpscale3DArray(smallChoice, 33, 5, 5, choice, 8, 4, 4); + + // Generate the shape: + int idxShape = 0; + for (int z = 0; z < cChunkDef::Width; z++) + { + for (int x = 0; x < cChunkDef::Width; x++) + { + int idxChoice = 257 * 17 * z + 257 * x; + NOISE_DATATYPE heightA = static_cast(cChunkDef::GetHeight(heightsA, x, z)); + NOISE_DATATYPE heightB = static_cast(cChunkDef::GetHeight(heightsB, x, z)); + for (int y = 0; y < cChunkDef::Height; y++) + { + int height = static_cast(ClampedLerp(heightA, heightB, choice[idxChoice++])); + a_Shape[idxShape++] = (y < height) ? 1 : 0; + } + } // for x + } // for z + } + + + virtual void InitializeShapeGen(cIniFile & a_IniFile) + { + m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyX", 40)); + m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyY", 40)); + m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyZ", 40)); + + // Initialize the two underlying height generators from an empty INI file: + cIniFile empty; + m_HeightA.InitializeHeightGen(empty); + m_HeightB.InitializeHeightGen(empty); + + // Add the choice octaves: + NOISE_DATATYPE freq = 0.001f; + NOISE_DATATYPE ampl = 1; + for (int i = 0; i < 4; i++) + { + m_Choice.AddOctave(freq, ampl); + freq = freq * 2; + ampl = ampl / 2; + } + } + +protected: + int m_Seed; + + /** The noise used to decide between the two heightmaps. */ + cOctavedNoise> m_Choice; + + /** The first height generator. */ + cHeiGenBiomal m_HeightA; + + /** The second height generator. */ + cHeiGenBiomal m_HeightB; + + /** The base frequencies for m_Choice in each of the world axis directions. */ + NOISE_DATATYPE m_FrequencyX, m_FrequencyY, m_FrequencyZ; +}; + + + + + +cTerrainShapeGenPtr CreateShapeGenTwoHeights(int a_Seed, cBiomeGenPtr a_BiomeGen) +{ + return std::make_shared(a_Seed, a_BiomeGen); +} + + + + diff --git a/src/Generating/TwoHeights.h b/src/Generating/TwoHeights.h new file mode 100644 index 000000000..353598011 --- /dev/null +++ b/src/Generating/TwoHeights.h @@ -0,0 +1,23 @@ + +// TwoHeights.h + +// Declares the function to create a new instance of the cTwoHeights terrain shape generator + + + + + +#pragma once + +#include "ComposableGenerator.h" + + + + +/** Creates and returns a new instance of the cTwoHeights terrain shape generator. +The instance must be Initialize()-d before it is used. */ +extern cTerrainShapeGenPtr CreateShapeGenTwoHeights(int a_Seed, cBiomeGenPtr a_BiomeGen); + + + + diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index a9b359b6a..f7d9a8316 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -18,8 +18,8 @@ /* How village generating works: -By descending from a cGridStructGen, a semi-random grid is generated. A village may be generated for each of -the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all +By descending from a cGridStructGen, a semi-random (jitter) grid is generated. A village may be generated for each +of the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell is left village-less. @@ -125,7 +125,7 @@ public: m_Noise(a_Seed), m_MaxSize(a_MaxSize), m_Density(a_Density), - m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize), + m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, cChunkDef::Height - 1, a_OriginZ + a_MaxSize), m_Prefabs(a_Prefabs), m_HeightGen(a_HeightGen), m_RoadBlock(a_RoadBlock), -- cgit v1.2.3 From e3e13f552fe717256e2ba4cb9bea7c00834d1ec4 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 27 Nov 2014 21:19:52 +0100 Subject: Fixed BlockStringToType return value. -1 was not a valid BLOCKTYPE and would not be recognized by the callers, ever. --- src/Generating/ChunkGenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index 92e1bb31d..3ee02c767 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -191,13 +191,13 @@ EMCSBiome cChunkGenerator::GetBiomeAt(int a_BlockX, int a_BlockZ) BLOCKTYPE cChunkGenerator::GetIniBlock(cIniFile & a_IniFile, const AString & a_SectionName, const AString & a_ValueName, const AString & a_Default) { AString BlockType = a_IniFile.GetValueSet(a_SectionName, a_ValueName, a_Default); - BLOCKTYPE Block = BlockStringToType(BlockType); + int Block = BlockStringToType(BlockType); if (Block < 0) { LOGWARN("[%s].%s Could not parse block value \"%s\". Using default: \"%s\".", a_SectionName.c_str(), a_ValueName.c_str(), BlockType.c_str(), a_Default.c_str()); - return BlockStringToType(a_Default); + return static_cast(BlockStringToType(a_Default)); } - return Block; + return static_cast(Block); } -- cgit v1.2.3 From 61ce09e4d0c5c86e4191010707d89ef02f5df29e Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 27 Nov 2014 21:24:03 +0100 Subject: CompoGenBiomal: Fixed signed vs unsigned comparison. --- src/Generating/CompoGenBiomal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGenBiomal.cpp b/src/Generating/CompoGenBiomal.cpp index 995851c95..030c2baa5 100644 --- a/src/Generating/CompoGenBiomal.cpp +++ b/src/Generating/CompoGenBiomal.cpp @@ -39,7 +39,7 @@ public: // Fill the rest with stone: static BlockInfo Stone = {E_BLOCK_STONE, 0}; - for (size_t i = a_Count; i < cChunkDef::Height; i++) + for (int i = static_cast(a_Count); i < cChunkDef::Height; i++) { m_Pattern[i] = Stone; } -- cgit v1.2.3 From 65dc452923f8db74f0fcb3869d4301cb10ee1ca6 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 30 Nov 2014 16:34:41 +0100 Subject: Fixed nether ceiling --- src/Generating/CompoGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 23cc64d78..6c3b50b4e 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -324,7 +324,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc: CeilingDisguise = -CeilingDisguise; } - int CeilingDisguiseHeight = Height - 2 - (int)CeilingDisguise * 3; + int CeilingDisguiseHeight = Height - 2 - FloorC(CeilingDisguise * 3); for (int y = Height - 1; y > CeilingDisguiseHeight; y--) { -- cgit v1.2.3 From e972c52e540ca49214d378207e2064f80bcb7983 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 30 Nov 2014 18:44:44 +0100 Subject: Hopefully fixed random build fails --- src/Generating/FinishGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 2ff3e7f67..1e8a67dd0 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -516,7 +516,7 @@ void cFinishGenSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) } int Height = a_ChunkDesc.GetHeight(x, z); - if (Height >= cChunkDef::Height) + if (Height >= cChunkDef::Height - 1) { // Too high up continue; -- cgit v1.2.3 From f0ad6221c3a409e7cc9cde631c50bc026486b4ae Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 1 Dec 2014 00:08:44 +0100 Subject: Noise3D: Fixed missing initialization. This should fix terrain being at Y=0 or Y=255 for the spawn chunk. Fixes #1433. --- src/Generating/Noise3DGenerator.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index a7af87bac..57e23809e 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -529,7 +529,9 @@ cBiomalNoise3DComposable::cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_Bi m_DensityNoiseA(a_Seed + 1), m_DensityNoiseB(a_Seed + 2), m_BaseNoise(a_Seed + 3), - m_BiomeGen(a_BiomeGen) + m_BiomeGen(a_BiomeGen), + m_LastChunkX(0x7fffffff), // Set impossible coords for the chunk so that it's always considered stale + m_LastChunkZ(0x7fffffff) { // Generate the weight distribution for summing up neighboring biomes: m_WeightSum = 0; -- cgit v1.2.3 From cc313c91ab0e62f269e30c9f525919b7b7bc61f5 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 1 Dec 2014 00:14:27 +0100 Subject: DistortedHeightmap: Added missing initialization. This was probably the original cause for the "empty chunks". Fixes #1433. --- src/Generating/DistortedHeightmap.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index e1ed9b450..37a51c18e 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -122,6 +122,8 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGenPtr a_BiomeGen) : m_NoiseDistortX(a_Seed + 1000), m_NoiseDistortZ(a_Seed + 2000), + m_CurChunkX(0x7fffffff), // Set impossible coords for the chunk so that it's always considered stale + m_CurChunkZ(0x7fffffff), m_BiomeGen(a_BiomeGen), m_UnderlyingHeiGen(new cHeiGenBiomal(a_Seed, a_BiomeGen)), m_HeightGen(m_UnderlyingHeiGen, 64), -- cgit v1.2.3 From fa4a85c91518575e600fbd5755dda179931d9436 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 1 Dec 2014 16:36:48 +0100 Subject: Added better soulsand rims As a finisher called SoulsandRims --- src/Generating/CompoGen.cpp | 12 +---- src/Generating/ComposableGenerator.cpp | 4 ++ src/Generating/FinishGen.cpp | 82 ++++++++++++++++++++++++++++++++++ src/Generating/FinishGen.h | 19 ++++++++ 4 files changed, 106 insertions(+), 11 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 6c3b50b4e..cb9c04fd7 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -290,17 +290,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc: BLOCKTYPE Block = E_BLOCK_AIR; if (Val < m_Threshold) // Don't calculate if the block should be Netherrack or Soulsand when it's already decided that it's air. { - NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(BaseX + x)) / 8; - NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(BaseZ + z)) / 8; - NOISE_DATATYPE CompBlock = m_Noise1.CubicNoise3D(NoiseX, (float) (y + Segment) / 2, NoiseY); - if (CompBlock < -0.5) - { - Block = E_BLOCK_SOULSAND; - } - else - { - Block = E_BLOCK_NETHERRACK; - } + Block = E_BLOCK_NETHERRACK; } a_ChunkDesc.SetBlockType(x, y + Segment, z, Block); } diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 4192dfa72..6b8923955 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -570,6 +570,10 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) GridSize, MaxOffset ))); } + else if (NoCaseCompare(*itr, "SoulsandRims") == 0) + { + m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSoulsandRims(Seed))); + } else if (NoCaseCompare(*itr, "Snow") == 0) { m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSnow)); diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 1e8a67dd0..898a9b268 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -391,6 +391,88 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) +//////////////////////////////////////////////////////////////////////////////// +// cFinishGenSoulsandRims + +void cFinishGenSoulsandRims::GenFinish(cChunkDesc & a_ChunkDesc) +{ + int ChunkX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; + int ChunkZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; + HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); + + for (int x = 0; x < 16; x++) + { + int xx = ChunkX + x; + for (int z = 0; z < 16; z++) + { + int zz = ChunkZ + z; + + // Place soulsand rims when netherrack gets thin + for (int y = 2; y < MaxHeight - 2; y++) + { + // The current block is air. Let's bail ut. + BLOCKTYPE Block = a_ChunkDesc.GetBlockType(x, y, z); + if (Block == E_BLOCK_AIR) + { + continue; + } + + // Check how many blocks there are above the current block. Don't go higher than 2 blocks, because we already bail out if that's the case. + int NumBlocksAbove = 0; + for (int I = y + 1; I <= y + 2; I++) + { + if (a_ChunkDesc.GetBlockType(x, I, z) != E_BLOCK_AIR) + { + NumBlocksAbove++; + } + else + { + break; + } + } + + // There are too many blocks above the current block. + if (NumBlocksAbove == 2) + { + continue; + } + + // Check how many blocks there below the current block. Don't go lower than 2 blocks, because we already bail out if that's the case. + int NumBlocksBelow = 0; + for (int I = y - 1; I >= y - 2; I--) + { + if (a_ChunkDesc.GetBlockType(x, I, z) != E_BLOCK_AIR) + { + NumBlocksBelow++; + } + else + { + break; + } + } + + // There are too many blocks below the current block + if (NumBlocksBelow == 2) + { + continue; + } + + NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(xx)) / 32; + NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(zz)) / 32; + NOISE_DATATYPE CompBlock = m_Noise.CubicNoise3D(NoiseX, (float) (y) / 4, NoiseY); + if (CompBlock < 0) + { + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SOULSAND); + } + } + } + } +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cFinishGenSnow: diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 991a85787..d45365683 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -117,6 +117,25 @@ protected: +class cFinishGenSoulsandRims : + public cFinishGen +{ +public: + cFinishGenSoulsandRims(int a_Seed) : + m_Noise(a_Seed) + { + } + +protected: + cNoise m_Noise; + + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; +} ; + + + + + class cFinishGenSprinkleFoliage : public cFinishGen { -- cgit v1.2.3 From 1bf0827a2f88b84df010e24ef52a5d472bd55eb7 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 1 Dec 2014 17:29:35 +0100 Subject: Simplefied SoulsandRims Replaced two for loops with a single if --- src/Generating/FinishGen.cpp | 42 ++++++------------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 898a9b268..b9d702429 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -417,42 +417,12 @@ void cFinishGenSoulsandRims::GenFinish(cChunkDesc & a_ChunkDesc) continue; } - // Check how many blocks there are above the current block. Don't go higher than 2 blocks, because we already bail out if that's the case. - int NumBlocksAbove = 0; - for (int I = y + 1; I <= y + 2; I++) - { - if (a_ChunkDesc.GetBlockType(x, I, z) != E_BLOCK_AIR) - { - NumBlocksAbove++; - } - else - { - break; - } - } - - // There are too many blocks above the current block. - if (NumBlocksAbove == 2) - { - continue; - } - - // Check how many blocks there below the current block. Don't go lower than 2 blocks, because we already bail out if that's the case. - int NumBlocksBelow = 0; - for (int I = y - 1; I >= y - 2; I--) - { - if (a_ChunkDesc.GetBlockType(x, I, z) != E_BLOCK_AIR) - { - NumBlocksBelow++; - } - else - { - break; - } - } - - // There are too many blocks below the current block - if (NumBlocksBelow == 2) + if ( + ((a_ChunkDesc.GetBlockType(x, y + 1, z) != E_BLOCK_AIR) && + ( a_ChunkDesc.GetBlockType(x, y + 2, z) != E_BLOCK_AIR)) || + ((a_ChunkDesc.GetBlockType(x, y - 1, z) != E_BLOCK_AIR) && + ( a_ChunkDesc.GetBlockType(x, y - 2, z) != E_BLOCK_AIR)) + ) { continue; } -- cgit v1.2.3 From c0b08a6c1e4666c1d3044a264fc47711e821ce14 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 1 Dec 2014 17:51:20 +0100 Subject: Dungeons spawners now spawn mobs 25% for a spider, 25% for a skeleton and 50% for a zombie spawner. --- src/Generating/DungeonRoomsFinisher.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 7ab22c2c5..0267c41fa 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -7,6 +7,7 @@ #include "DungeonRoomsFinisher.h" #include "../FastRandom.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/MobSpawnerEntity.h" @@ -57,6 +58,22 @@ public: int SecondChestPos = (FirstChestPos + 2 + (rnd % (NumPositions - 3))) % NumPositions; m_Chest1 = DecodeChestCoords(FirstChestPos, SizeX, SizeZ); m_Chest2 = DecodeChestCoords(SecondChestPos, SizeX, SizeZ); + + // Choose what the mobspawner will spawn. + // 25% chance for a spider, 25% for a skeleton and 50% chance to get a zombie spawer. + NOISE_DATATYPE MobType = a_Noise.IntNoise3D(a_OriginX, m_FloorHeight, a_OriginZ); + if (MobType <= -0.5) + { + m_MonsterType = mtSkeleton; + } + else if (MobType <= 0) + { + m_MonsterType = mtSpider; + } + else + { + m_MonsterType = mtZombie; + } } protected: @@ -76,6 +93,8 @@ protected: /** The (absolute) coords of the second chest. The Y coord represents the chest's Meta value (facing). */ Vector3i m_Chest2; + /** The monster type for the mobspawner entity. */ + eMonsterType m_MonsterType; /** Decodes the position index along the room walls into a proper 2D position for a chest. @@ -246,7 +265,9 @@ protected: ) { a_ChunkDesc.SetBlockTypeMeta(CenterX, b, CenterZ, E_BLOCK_MOB_SPAWNER, 0); - // TODO: Set the spawned mob + cMobSpawnerEntity * MobSpawner = (cMobSpawnerEntity *)a_ChunkDesc.GetBlockEntity(CenterX, b, CenterZ); + ASSERT((MobSpawner != nullptr) && (MobSpawner->GetBlockType() == E_BLOCK_MOB_SPAWNER)); + MobSpawner->SetEntity(m_MonsterType); } } } ; -- cgit v1.2.3 From 25e3869485106966aebbf0041f416d61c41114db Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 1 Dec 2014 18:47:39 +0100 Subject: Mineshaft spawners now spawn cave spiders --- src/Generating/MineShafts.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp index 55b3b64dd..33835160c 100644 --- a/src/Generating/MineShafts.cpp +++ b/src/Generating/MineShafts.cpp @@ -20,6 +20,7 @@ in a depth-first processing. Each of the descendants will branch randomly, if no #include "MineShafts.h" #include "../Cuboid.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/MobSpawnerEntity.h" @@ -875,7 +876,9 @@ void cMineShaftCorridor::PlaceSpawner(cChunkDesc & a_ChunkDesc) ) { a_ChunkDesc.SetBlockTypeMeta(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ, E_BLOCK_MOB_SPAWNER, 0); - // TODO: The spawner needs its accompanying cMobSpawnerEntity, when implemented + cMobSpawnerEntity * MobSpawner = (cMobSpawnerEntity *)a_ChunkDesc.GetBlockEntity(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ); + ASSERT((MobSpawner != nullptr) && (MobSpawner->GetBlockType() == E_BLOCK_MOB_SPAWNER)); + MobSpawner->SetEntity(mtCaveSpider); } } -- cgit v1.2.3 From ca728da9b6c0ac433907ee95db622ec961facd1f Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 1 Dec 2014 19:05:44 +0100 Subject: Using static cast for MineShaft spawners --- src/Generating/MineShafts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp index 33835160c..65588ce4b 100644 --- a/src/Generating/MineShafts.cpp +++ b/src/Generating/MineShafts.cpp @@ -876,7 +876,7 @@ void cMineShaftCorridor::PlaceSpawner(cChunkDesc & a_ChunkDesc) ) { a_ChunkDesc.SetBlockTypeMeta(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ, E_BLOCK_MOB_SPAWNER, 0); - cMobSpawnerEntity * MobSpawner = (cMobSpawnerEntity *)a_ChunkDesc.GetBlockEntity(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ); + cMobSpawnerEntity * MobSpawner = static_cast(a_ChunkDesc.GetBlockEntity(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ)); ASSERT((MobSpawner != nullptr) && (MobSpawner->GetBlockType() == E_BLOCK_MOB_SPAWNER)); MobSpawner->SetEntity(mtCaveSpider); } -- cgit v1.2.3 From 7586069829af86a03f900daebc0cbf9622071f30 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 1 Dec 2014 19:07:54 +0100 Subject: Using static cast for Dungeon spawners --- src/Generating/DungeonRoomsFinisher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 0267c41fa..492ab1ed9 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -265,7 +265,7 @@ protected: ) { a_ChunkDesc.SetBlockTypeMeta(CenterX, b, CenterZ, E_BLOCK_MOB_SPAWNER, 0); - cMobSpawnerEntity * MobSpawner = (cMobSpawnerEntity *)a_ChunkDesc.GetBlockEntity(CenterX, b, CenterZ); + cMobSpawnerEntity * MobSpawner = static_cast(a_ChunkDesc.GetBlockEntity(CenterX, b, CenterZ)); ASSERT((MobSpawner != nullptr) && (MobSpawner->GetBlockType() == E_BLOCK_MOB_SPAWNER)); MobSpawner->SetEntity(m_MonsterType); } -- cgit v1.2.3 From cb584a87bd8336d590941cec0c204cbf75ab53eb Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Mon, 1 Dec 2014 11:44:20 -0800 Subject: cacti no longer spawn outside of desert variants --- src/Generating/FinishGen.cpp | 14 +++++++++++++- src/Generating/FinishGen.h | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index b9d702429..e09646758 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -370,7 +370,8 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) (a_ChunkDesc.GetBlockType(x + 1, y, z) == E_BLOCK_AIR) && (a_ChunkDesc.GetBlockType(x - 1, y, z) == E_BLOCK_AIR) && (a_ChunkDesc.GetBlockType(x, y, z + 1) == E_BLOCK_AIR) && - (a_ChunkDesc.GetBlockType(x, y, z - 1) == E_BLOCK_AIR) + (a_ChunkDesc.GetBlockType(x, y, z - 1) == E_BLOCK_AIR) && + IsDesertVariant(a_ChunkDesc.GetBiome(x, z) ) { a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_CACTUS); @@ -391,6 +392,17 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) +bool cFinishGenSprinkleFoliage::IsDesertVariant(EMCSBiome a_biome) +{ + return a_biome == biDesertHills || + a_biome == biDesert || + a_biome == biDesertM; +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cFinishGenSoulsandRims diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index d45365683..16128efa5 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -149,6 +149,9 @@ protected: /// Tries to place sugarcane at the coords specified, returns true if successful bool TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ); + // Checks if biome is a desert to spawn cacti as opposed to just sand + bool IsDesertVariant(EMCSBiome a_biome); + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; -- cgit v1.2.3 From 3bf111c69e11623947da70520063c57238d67bf0 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Mon, 1 Dec 2014 17:28:46 -0800 Subject: formatting and commenting fixes --- src/Generating/FinishGen.cpp | 8 ++++---- src/Generating/FinishGen.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index e09646758..cba45c0a1 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -392,11 +392,11 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) -bool cFinishGenSprinkleFoliage::IsDesertVariant(EMCSBiome a_biome) +bool cFinishGenSprinkleFoliage::IsDesertVariant(EMCSBiome a_Biome) { - return a_biome == biDesertHills || - a_biome == biDesert || - a_biome == biDesertM; + return (a_Biome == biDesertHills) || + (a_Biome == biDesert ) || + (a_Biome == biDesertM ); } diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 16128efa5..dd6a09c6a 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -149,8 +149,8 @@ protected: /// Tries to place sugarcane at the coords specified, returns true if successful bool TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ); - // Checks if biome is a desert to spawn cacti as opposed to just sand - bool IsDesertVariant(EMCSBiome a_biome); + // Returns true is the specified biome is a desert or its variant + static bool IsDesertVariant(EMCSBiome a_biome); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; -- cgit v1.2.3 From bb5a7d8f151bc7c2426f16becc5f7a0c70ca7fef Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Mon, 1 Dec 2014 17:47:36 -0800 Subject: reformat for lua and CI --- src/Generating/FinishGen.cpp | 13 ++++++++----- src/Generating/FinishGen.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index cba45c0a1..7ef658dc2 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -371,7 +371,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) (a_ChunkDesc.GetBlockType(x - 1, y, z) == E_BLOCK_AIR) && (a_ChunkDesc.GetBlockType(x, y, z + 1) == E_BLOCK_AIR) && (a_ChunkDesc.GetBlockType(x, y, z - 1) == E_BLOCK_AIR) && - IsDesertVariant(a_ChunkDesc.GetBiome(x, z) + IsDesertVariant(a_ChunkDesc.GetBiome(x, z)) ) { a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_CACTUS); @@ -394,9 +394,12 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) bool cFinishGenSprinkleFoliage::IsDesertVariant(EMCSBiome a_Biome) { - return (a_Biome == biDesertHills) || - (a_Biome == biDesert ) || - (a_Biome == biDesertM ); + return + ( + (a_Biome == biDesertHills) || + (a_Biome == biDesert) || + (a_Biome == biDesertM) + ); } @@ -412,7 +415,7 @@ void cFinishGenSoulsandRims::GenFinish(cChunkDesc & a_ChunkDesc) int ChunkZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); - for (int x = 0; x < 16; x++) + for (int x = 0; x < 16; x++) { int xx = ChunkX + x; for (int z = 0; z < 16; z++) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index dd6a09c6a..d8d67671d 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -121,7 +121,7 @@ class cFinishGenSoulsandRims : public cFinishGen { public: - cFinishGenSoulsandRims(int a_Seed) : + cFinishGenSoulsandRims(int a_Seed) : m_Noise(a_Seed) { } -- cgit v1.2.3 From 5db3ceb333e5a705de3ff03834d1c212e1c38e63 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 2 Dec 2014 09:42:49 +0100 Subject: Suggestions by xoft Using IntNoise3D to prevent needless floating point math --- src/Generating/DungeonRoomsFinisher.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 492ab1ed9..19ac3b8b2 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -61,12 +61,12 @@ public: // Choose what the mobspawner will spawn. // 25% chance for a spider, 25% for a skeleton and 50% chance to get a zombie spawer. - NOISE_DATATYPE MobType = a_Noise.IntNoise3D(a_OriginX, m_FloorHeight, a_OriginZ); - if (MobType <= -0.5) + int MobType = (a_Noise.IntNoise3D(a_OriginX, m_FloorHeight, a_OriginZ) / 7) % 100 + if (MobType <= 25) { m_MonsterType = mtSkeleton; } - else if (MobType <= 0) + else if (MobType <= 50) { m_MonsterType = mtSpider; } -- cgit v1.2.3 From a466986f53c2bec54bc25951d05036db5a3fb2e1 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 2 Dec 2014 09:55:25 +0100 Subject: Using IntNoise3DInt instead of IntNoise3D --- src/Generating/DungeonRoomsFinisher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 19ac3b8b2..847fcbf10 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -61,7 +61,7 @@ public: // Choose what the mobspawner will spawn. // 25% chance for a spider, 25% for a skeleton and 50% chance to get a zombie spawer. - int MobType = (a_Noise.IntNoise3D(a_OriginX, m_FloorHeight, a_OriginZ) / 7) % 100 + int MobType = (a_Noise.IntNoise3DInt(a_OriginX, m_FloorHeight, a_OriginZ) / 7) % 100 if (MobType <= 25) { m_MonsterType = mtSkeleton; -- cgit v1.2.3 From f1177984f102e7b9c8cdc9ca5e8d9b5c67a4330f Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 2 Dec 2014 10:20:20 +0100 Subject: Fixed forgotten semicolon --- src/Generating/DungeonRoomsFinisher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 847fcbf10..092e232ab 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -61,7 +61,7 @@ public: // Choose what the mobspawner will spawn. // 25% chance for a spider, 25% for a skeleton and 50% chance to get a zombie spawer. - int MobType = (a_Noise.IntNoise3DInt(a_OriginX, m_FloorHeight, a_OriginZ) / 7) % 100 + int MobType = (a_Noise.IntNoise3DInt(a_OriginX, m_FloorHeight, a_OriginZ) / 7) % 100; if (MobType <= 25) { m_MonsterType = mtSkeleton; -- cgit v1.2.3 From 9831220a1cfc84804619e497f8b56853de98bf82 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 01:37:17 -0800 Subject: animal terrain finisher --- src/Generating/FinishGen.cpp | 212 +++++++++++++++++++++++++++++++++++++++++++ src/Generating/FinishGen.h | 29 ++++++ 2 files changed, 241 insertions(+) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index b9d702429..b8575f4f8 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -26,6 +26,8 @@ #define DEF_OVERWORLD_LAVA_SPRINGS "0, 0; 10, 5; 11, 45; 48, 2; 64, 1; 255, 0" #define DEF_END_WATER_SPRINGS "0, 1; 255, 1" #define DEF_END_LAVA_SPRINGS "0, 1; 255, 1" +#define DEF_ANIMAL_SPAWN_PERCENT 10 +#define DEF_NO_ANIMALS 0 @@ -943,3 +945,213 @@ bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int + +//////////////////////////////////////////////////////////////////////////////// +// cFinishGenPassiveMobs: + +cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension) : + m_Noise(a_Seed) +{ + AString SectionName = "Animals"; + int DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; + switch (a_Dimension) + { + case dimOverworld: + { + DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; + break; + } + case dimNether: + case dimEnd: // No nether or end animals (currently) + { + DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; + break; + } + default: + { + ASSERT(!"Unhandled world dimension"); + break; + } + } // switch (dimension) + m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); + if (m_AnimalProbability < 0 || m_AnimalProbability > 100) + { + LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); + } +} + + + + + +void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) +{ + int ChanceRnd = m_Random.NextInt(100); + if (ChanceRnd > m_AnimalProbability) + { + return; + } + + eMonsterType RandomMob = GetRandomMob(a_ChunkDesc); + if (RandomMob == mtInvalidType) + { + LOGWARNING("Attempted to spawn invalid mob type."); + return; + } + + // Try spawning a pack center 10 times, should get roughly the same probability + for (int Tries = 0; Tries < 10; Tries++) + { + int PackCenterX = m_Random.NextInt(cChunkDef::Width - 1); + int PackCenterZ = m_Random.NextInt(cChunkDef::Width - 1); + if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) + { + for (int i = 0; i < 5; i++) + { + int OffsetX = m_Random.NextInt(cChunkDef::Width - 1); + int OffsetZ = m_Random.NextInt(cChunkDef::Width - 1); + TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); + } + + return; + + } // if pack center spawn successful + } // for tries +} + + + + + +bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, eMonsterType AnimalToSpawn) +{ + BLOCKTYPE BlockAtHead = a_ChunkDesc.GetBlockType(a_RelX, a_RelY + 1, a_RelZ); + BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY , a_RelZ); + BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); + + // Check block below (opaque, grass, water), and above (air) + if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) + { + return false; + } + if ( + (AnimalToSpawn != mtSquid) && + (BlockAtHead != E_BLOCK_AIR) && + (BlockAtFeet != E_BLOCK_AIR) && + (!cBlockInfo::IsTransparent(BlockUnderFeet)) + ) + { + return false; + } + if ( + (BlockUnderFeet != E_BLOCK_GRASS) && + ( + (AnimalToSpawn == mtSheep) || + (AnimalToSpawn == mtChicken) || + (AnimalToSpawn == mtPig) + ) + ) + { + return false; + } + + int AnimalX, AnimalY, AnimalZ; + AnimalX = (double)(a_ChunkDesc.GetChunkX()*cChunkDef::Width + a_RelX + 0.5); + AnimalY = a_RelY; + AnimalZ = (double)(a_ChunkDesc.GetChunkZ()*cChunkDef::Width + a_RelZ + 0.5); + + cEntityList ChunkEntities = a_ChunkDesc.GetEntities(); + cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn); + NewMob->SetPosition(AnimalX, AnimalY, AnimalZ); + ChunkEntities.push_back(NewMob); + LOGD("Spawning %s #%i at {%d, %d, %d}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ); + + return true; +} + + + + + +eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) +{ + + std::set ListOfSpawnables; + std::set::iterator MobIter = ListOfSpawnables.begin(); + int x = m_Random.NextInt(cChunkDef::Width - 1); + int z = m_Random.NextInt(cChunkDef::Width - 1); + + // Check biomes first to get a list of animals + switch (a_ChunkDesc.GetBiome(x, z)) + { + // No animals + case biNether: + case biEnd: + return mtInvalidType; + + // Squid only + case biOcean: + case biFrozenOcean: + case biFrozenRiver: + case biRiver: + case biDeepOcean: + ListOfSpawnables.insert(MobIter, mtSquid); + break; + + // Mooshroom only + case biMushroomIsland: + case biMushroomShore: + ListOfSpawnables.insert(MobIter, mtMooshroom); + break; + + case biJungle: + case biJungleHills: + case biJungleEdge: + case biJungleM: + case biJungleEdgeM: + ListOfSpawnables.insert(MobIter, mtOcelot); + + case biPlains: + case biSunflowerPlains: + case biSavanna: + case biSavannaPlateau: + case biSavannaM: + case biSavannaPlateauM: + ListOfSpawnables.insert(MobIter, mtHorse); + // ListOfSpawnables.insert(mtDonkey); + + // Wolves only + case biForest: + case biTaiga: + case biMegaTaiga: + case biColdTaiga: + case biColdTaigaM: + ListOfSpawnables.insert(MobIter, mtWolf); + + // All other mobs + default: + ListOfSpawnables.insert(MobIter, mtChicken); + ListOfSpawnables.insert(MobIter, mtCow); + ListOfSpawnables.insert(MobIter, mtPig); + ListOfSpawnables.insert(MobIter, mtSheep); + } + + if (ListOfSpawnables.size() == 0) + { + LOGD("Tried to spawn an animal from an empty list."); + return mtInvalidType; + } + + int RandMob = m_Random.NextInt(ListOfSpawnables.size()); + MobIter=ListOfSpawnables.begin(); + for (int i = 0; i < RandMob; i++) + { + ++MobIter; + } + + return *MobIter; +} + + + + diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index d45365683..38bb93d2a 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -18,6 +18,8 @@ #include "ComposableGenerator.h" #include "../Noise/Noise.h" #include "../ProbabDistrib.h" +#include "../Mobs/Monster.h" +#include "FastRandom.h" @@ -315,3 +317,30 @@ protected: + +class cFinishGenPassiveMobs : + public cFinishGen +{ +public: + + cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension); + +protected: + + cNoise m_Noise; + int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk + cFastRandom m_Random; + + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; + + // Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. + bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); + + // Gets a random mob from biome-dependant list + eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); +} ; + + + + -- cgit v1.2.3 From 2d93274a90a86829ff6edfa02dd575c8811a6cfd Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 01:58:30 -0800 Subject: animal terrain finisher --- src/Generating/FinishGen.cpp | 350 +++++++++++++++++++++---------------------- src/Generating/FinishGen.h | 24 +-- 2 files changed, 187 insertions(+), 187 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index b8575f4f8..296e92139 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -402,7 +402,7 @@ void cFinishGenSoulsandRims::GenFinish(cChunkDesc & a_ChunkDesc) int ChunkZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); - for (int x = 0; x < 16; x++) + for (int x = 0; x < 16; x++) { int xx = ChunkX + x; for (int z = 0; z < 16; z++) @@ -950,34 +950,34 @@ bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int // cFinishGenPassiveMobs: cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension) : - m_Noise(a_Seed) + m_Noise(a_Seed) { - AString SectionName = "Animals"; - int DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; - switch (a_Dimension) - { - case dimOverworld: - { - DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; - break; - } - case dimNether: - case dimEnd: // No nether or end animals (currently) - { - DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; - break; - } - default: - { - ASSERT(!"Unhandled world dimension"); - break; - } - } // switch (dimension) - m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); - if (m_AnimalProbability < 0 || m_AnimalProbability > 100) - { - LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); - } + AString SectionName = "Animals"; + int DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; + switch (a_Dimension) + { + case dimOverworld: + { + DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; + break; + } + case dimNether: + case dimEnd:// No nether or end animals (currently) + { + DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; + break; + } + default: + { + ASSERT(!"Unhandled world dimension"); + break; + } + }// switch (dimension) + m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); + if (m_AnimalProbability < 0 || m_AnimalProbability > 100) + { + LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); + } } @@ -986,37 +986,37 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) { - int ChanceRnd = m_Random.NextInt(100); - if (ChanceRnd > m_AnimalProbability) - { - return; - } - - eMonsterType RandomMob = GetRandomMob(a_ChunkDesc); - if (RandomMob == mtInvalidType) - { - LOGWARNING("Attempted to spawn invalid mob type."); - return; - } - - // Try spawning a pack center 10 times, should get roughly the same probability - for (int Tries = 0; Tries < 10; Tries++) - { - int PackCenterX = m_Random.NextInt(cChunkDef::Width - 1); - int PackCenterZ = m_Random.NextInt(cChunkDef::Width - 1); - if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) - { - for (int i = 0; i < 5; i++) - { - int OffsetX = m_Random.NextInt(cChunkDef::Width - 1); - int OffsetZ = m_Random.NextInt(cChunkDef::Width - 1); - TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); - } - - return; - - } // if pack center spawn successful - } // for tries + int ChanceRnd = m_Random.NextInt(100); + if (ChanceRnd > m_AnimalProbability) + { + return; + } + + eMonsterType RandomMob = GetRandomMob(a_ChunkDesc); + if (RandomMob == mtInvalidType) + { + LOGWARNING("Attempted to spawn invalid mob type."); + return; + } + + // Try spawning a pack center 10 times, should get roughly the same probability + for (int Tries = 0; Tries < 10; Tries++) + { + int PackCenterX = m_Random.NextInt(cChunkDef::Width - 1); + int PackCenterZ = m_Random.NextInt(cChunkDef::Width - 1); + if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) + { + for (int i = 0; i < 5; i++) + { + int OffsetX = m_Random.NextInt(cChunkDef::Width - 1); + int OffsetZ = m_Random.NextInt(cChunkDef::Width - 1); + TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); + } + + return; + + }// if pack center spawn successful + }// for tries } @@ -1025,48 +1025,48 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, eMonsterType AnimalToSpawn) { - BLOCKTYPE BlockAtHead = a_ChunkDesc.GetBlockType(a_RelX, a_RelY + 1, a_RelZ); - BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY , a_RelZ); - BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); - - // Check block below (opaque, grass, water), and above (air) - if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) - { - return false; - } - if ( - (AnimalToSpawn != mtSquid) && - (BlockAtHead != E_BLOCK_AIR) && - (BlockAtFeet != E_BLOCK_AIR) && - (!cBlockInfo::IsTransparent(BlockUnderFeet)) - ) - { - return false; - } - if ( - (BlockUnderFeet != E_BLOCK_GRASS) && - ( - (AnimalToSpawn == mtSheep) || - (AnimalToSpawn == mtChicken) || - (AnimalToSpawn == mtPig) - ) - ) - { - return false; - } - - int AnimalX, AnimalY, AnimalZ; - AnimalX = (double)(a_ChunkDesc.GetChunkX()*cChunkDef::Width + a_RelX + 0.5); - AnimalY = a_RelY; - AnimalZ = (double)(a_ChunkDesc.GetChunkZ()*cChunkDef::Width + a_RelZ + 0.5); - - cEntityList ChunkEntities = a_ChunkDesc.GetEntities(); - cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn); - NewMob->SetPosition(AnimalX, AnimalY, AnimalZ); - ChunkEntities.push_back(NewMob); - LOGD("Spawning %s #%i at {%d, %d, %d}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ); - - return true; + BLOCKTYPE BlockAtHead = a_ChunkDesc.GetBlockType(a_RelX, a_RelY + 1, a_RelZ); + BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ); + BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); + + // Check block below (opaque, grass, water), and above (air) + if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) + { + return false; + } + if ( + (AnimalToSpawn != mtSquid) && + (BlockAtHead != E_BLOCK_AIR) && + (BlockAtFeet != E_BLOCK_AIR) && + (!cBlockInfo::IsTransparent(BlockUnderFeet)) + ) + { + return false; + } + if ( + (BlockUnderFeet != E_BLOCK_GRASS) && + ( + (AnimalToSpawn == mtSheep) || + (AnimalToSpawn == mtChicken) || + (AnimalToSpawn == mtPig) + ) + ) + { + return false; + } + + int AnimalX, AnimalY, AnimalZ; + AnimalX = (double)(a_ChunkDesc.GetChunkX()*cChunkDef::Width + a_RelX + 0.5); + AnimalY = a_RelY; + AnimalZ = (double)(a_ChunkDesc.GetChunkZ()*cChunkDef::Width + a_RelZ + 0.5); + + cEntityList ChunkEntities = a_ChunkDesc.GetEntities(); + cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn); + NewMob->SetPosition(AnimalX, AnimalY, AnimalZ); + ChunkEntities.push_back(NewMob); + LOGD("Spawning %s #%i at {%d, %d, %d}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ); + + return true; } @@ -1076,80 +1076,80 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) { - std::set ListOfSpawnables; - std::set::iterator MobIter = ListOfSpawnables.begin(); - int x = m_Random.NextInt(cChunkDef::Width - 1); - int z = m_Random.NextInt(cChunkDef::Width - 1); - - // Check biomes first to get a list of animals - switch (a_ChunkDesc.GetBiome(x, z)) - { - // No animals - case biNether: - case biEnd: - return mtInvalidType; - - // Squid only - case biOcean: - case biFrozenOcean: - case biFrozenRiver: - case biRiver: - case biDeepOcean: - ListOfSpawnables.insert(MobIter, mtSquid); - break; - - // Mooshroom only - case biMushroomIsland: - case biMushroomShore: - ListOfSpawnables.insert(MobIter, mtMooshroom); - break; - - case biJungle: - case biJungleHills: - case biJungleEdge: - case biJungleM: - case biJungleEdgeM: - ListOfSpawnables.insert(MobIter, mtOcelot); - - case biPlains: - case biSunflowerPlains: - case biSavanna: - case biSavannaPlateau: - case biSavannaM: - case biSavannaPlateauM: - ListOfSpawnables.insert(MobIter, mtHorse); - // ListOfSpawnables.insert(mtDonkey); - - // Wolves only - case biForest: - case biTaiga: - case biMegaTaiga: - case biColdTaiga: - case biColdTaigaM: - ListOfSpawnables.insert(MobIter, mtWolf); - - // All other mobs - default: - ListOfSpawnables.insert(MobIter, mtChicken); - ListOfSpawnables.insert(MobIter, mtCow); - ListOfSpawnables.insert(MobIter, mtPig); - ListOfSpawnables.insert(MobIter, mtSheep); - } - - if (ListOfSpawnables.size() == 0) - { - LOGD("Tried to spawn an animal from an empty list."); - return mtInvalidType; - } - - int RandMob = m_Random.NextInt(ListOfSpawnables.size()); - MobIter=ListOfSpawnables.begin(); - for (int i = 0; i < RandMob; i++) - { - ++MobIter; - } - - return *MobIter; + std::set ListOfSpawnables; + std::set::iterator MobIter = ListOfSpawnables.begin(); + int x = m_Random.NextInt(cChunkDef::Width - 1); + int z = m_Random.NextInt(cChunkDef::Width - 1); + + // Check biomes first to get a list of animals + switch (a_ChunkDesc.GetBiome(x, z)) + { + // No animals + case biNether: + case biEnd: + return mtInvalidType; + + // Squid only + case biOcean: + case biFrozenOcean: + case biFrozenRiver: + case biRiver: + case biDeepOcean: + ListOfSpawnables.insert(MobIter, mtSquid); + break; + + // Mooshroom only + case biMushroomIsland: + case biMushroomShore: + ListOfSpawnables.insert(MobIter, mtMooshroom); + break; + + case biJungle: + case biJungleHills: + case biJungleEdge: + case biJungleM: + case biJungleEdgeM: + ListOfSpawnables.insert(MobIter, mtOcelot); + + case biPlains: + case biSunflowerPlains: + case biSavanna: + case biSavannaPlateau: + case biSavannaM: + case biSavannaPlateauM: + ListOfSpawnables.insert(MobIter, mtHorse); + // ListOfSpawnables.insert(mtDonkey); + + // Wolves only + case biForest: + case biTaiga: + case biMegaTaiga: + case biColdTaiga: + case biColdTaigaM: + ListOfSpawnables.insert(MobIter, mtWolf); + + // All other mobs + default: + ListOfSpawnables.insert(MobIter, mtChicken); + ListOfSpawnables.insert(MobIter, mtCow); + ListOfSpawnables.insert(MobIter, mtPig); + ListOfSpawnables.insert(MobIter, mtSheep); + } + + if (ListOfSpawnables.size() == 0) + { + LOGD("Tried to spawn an animal from an empty list."); + return mtInvalidType; + } + + int RandMob = m_Random.NextInt(ListOfSpawnables.size()); + MobIter=ListOfSpawnables.begin(); + for (int i = 0; i < RandMob; i++) + { + ++MobIter; + } + + return *MobIter; } diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 38bb93d2a..c8575f4d1 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -123,7 +123,7 @@ class cFinishGenSoulsandRims : public cFinishGen { public: - cFinishGenSoulsandRims(int a_Seed) : + cFinishGenSoulsandRims(int a_Seed) : m_Noise(a_Seed) { } @@ -319,26 +319,26 @@ protected: class cFinishGenPassiveMobs : - public cFinishGen + public cFinishGen { public: - cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension); + cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension); protected: - cNoise m_Noise; - int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk - cFastRandom m_Random; + cNoise m_Noise; + int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk + cFastRandom m_Random; - // cFinishGen override: - virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; + // cFinishGen override: + virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - // Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. - bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); + // Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. + bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); - // Gets a random mob from biome-dependant list - eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); + // Gets a random mob from biome-dependant list + eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); } ; -- cgit v1.2.3 From 978c9967adb4dbafdb6ade3f05345d473fcef2e5 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 02:03:29 -0800 Subject: fix comments after replacing spaces with tabs --- src/Generating/FinishGen.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 296e92139..2b0194a27 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -962,7 +962,7 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e break; } case dimNether: - case dimEnd:// No nether or end animals (currently) + case dimEnd: // No nether or end animals (currently) { DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; break; @@ -972,7 +972,7 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e ASSERT(!"Unhandled world dimension"); break; } - }// switch (dimension) + } // switch (dimension) m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); if (m_AnimalProbability < 0 || m_AnimalProbability > 100) { @@ -1015,8 +1015,8 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) return; - }// if pack center spawn successful - }// for tries + } // if pack center spawn successful + } // for tries } -- cgit v1.2.3 From 585662e63f33470a6c241340f0b527102fcf406a Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 11:21:51 -0800 Subject: indentation, repeatable random, small corrections --- src/Generating/FinishGen.cpp | 191 +++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 98 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 2b0194a27..3e5b24017 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -956,27 +956,27 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e int DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; switch (a_Dimension) { - case dimOverworld: - { - DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; - break; - } - case dimNether: - case dimEnd: // No nether or end animals (currently) - { - DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; - break; - } - default: - { - ASSERT(!"Unhandled world dimension"); - break; - } + case dimOverworld: + { + DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; + break; + } + case dimNether: + case dimEnd: // No nether or end animals (currently) + { + DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; + break; + } + default: + { + ASSERT(!"Unhandled world dimension"); + break; + } } // switch (dimension) m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); if (m_AnimalProbability < 0 || m_AnimalProbability > 100) { - LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); + LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); } } @@ -986,33 +986,32 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) { - int ChanceRnd = m_Random.NextInt(100); + int ChanceRnd = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % 100; if (ChanceRnd > m_AnimalProbability) { - return; + return; } eMonsterType RandomMob = GetRandomMob(a_ChunkDesc); if (RandomMob == mtInvalidType) { - LOGWARNING("Attempted to spawn invalid mob type."); - return; + LOGWARNING("Attempted to spawn invalid mob type."); + return; } // Try spawning a pack center 10 times, should get roughly the same probability for (int Tries = 0; Tries < 10; Tries++) { - int PackCenterX = m_Random.NextInt(cChunkDef::Width - 1); - int PackCenterZ = m_Random.NextInt(cChunkDef::Width - 1); + int PackCenterX = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; + int PackCenterZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) { for (int i = 0; i < 5; i++) { - int OffsetX = m_Random.NextInt(cChunkDef::Width - 1); - int OffsetZ = m_Random.NextInt(cChunkDef::Width - 1); + int OffsetX = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; + int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); } - return; } // if pack center spawn successful @@ -1032,27 +1031,24 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX // Check block below (opaque, grass, water), and above (air) if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) { - return false; + return false; } - if ( - (AnimalToSpawn != mtSquid) && - (BlockAtHead != E_BLOCK_AIR) && - (BlockAtFeet != E_BLOCK_AIR) && - (!cBlockInfo::IsTransparent(BlockUnderFeet)) + if ((AnimalToSpawn != mtSquid) && + (BlockAtHead != E_BLOCK_AIR) && + (BlockAtFeet != E_BLOCK_AIR) && + (!cBlockInfo::IsTransparent(BlockUnderFeet)) ) { - return false; + return false; } - if ( - (BlockUnderFeet != E_BLOCK_GRASS) && - ( - (AnimalToSpawn == mtSheep) || - (AnimalToSpawn == mtChicken) || - (AnimalToSpawn == mtPig) - ) - ) + if ((BlockUnderFeet != E_BLOCK_GRASS) && + ((AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig))) { - return false; + return false; + } + if (AnimalToSpawn == mtMooshroom && BlockUnderFeet != E_BLOCK_MYCELIUM) + { + return false; } int AnimalX, AnimalY, AnimalZ; @@ -1078,75 +1074,74 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) std::set ListOfSpawnables; std::set::iterator MobIter = ListOfSpawnables.begin(); - int x = m_Random.NextInt(cChunkDef::Width - 1); - int z = m_Random.NextInt(cChunkDef::Width - 1); + int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; + int z = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; // Check biomes first to get a list of animals switch (a_ChunkDesc.GetBiome(x, z)) { - // No animals - case biNether: - case biEnd: - return mtInvalidType; - - // Squid only - case biOcean: - case biFrozenOcean: - case biFrozenRiver: - case biRiver: - case biDeepOcean: - ListOfSpawnables.insert(MobIter, mtSquid); - break; - - // Mooshroom only - case biMushroomIsland: - case biMushroomShore: - ListOfSpawnables.insert(MobIter, mtMooshroom); - break; - - case biJungle: - case biJungleHills: - case biJungleEdge: - case biJungleM: - case biJungleEdgeM: - ListOfSpawnables.insert(MobIter, mtOcelot); - - case biPlains: - case biSunflowerPlains: - case biSavanna: - case biSavannaPlateau: - case biSavannaM: - case biSavannaPlateauM: - ListOfSpawnables.insert(MobIter, mtHorse); - // ListOfSpawnables.insert(mtDonkey); - - // Wolves only - case biForest: - case biTaiga: - case biMegaTaiga: - case biColdTaiga: - case biColdTaigaM: - ListOfSpawnables.insert(MobIter, mtWolf); - - // All other mobs - default: - ListOfSpawnables.insert(MobIter, mtChicken); - ListOfSpawnables.insert(MobIter, mtCow); - ListOfSpawnables.insert(MobIter, mtPig); - ListOfSpawnables.insert(MobIter, mtSheep); + // No animals + case biNether: + case biEnd: + return mtInvalidType; + + // Squid only + case biOcean: + case biFrozenOcean: + case biFrozenRiver: + case biRiver: + case biDeepOcean: + ListOfSpawnables.insert(MobIter, mtSquid); + break; + + // Mooshroom only + case biMushroomIsland: + case biMushroomShore: + ListOfSpawnables.insert(MobIter, mtMooshroom); + break; + + case biJungle: + case biJungleHills: + case biJungleEdge: + case biJungleM: + case biJungleEdgeM: + ListOfSpawnables.insert(MobIter, mtOcelot); + + case biPlains: + case biSunflowerPlains: + case biSavanna: + case biSavannaPlateau: + case biSavannaM: + case biSavannaPlateauM: + ListOfSpawnables.insert(MobIter, mtHorse); + // ListOfSpawnables.insert(mtDonkey); + + // Wolves only + case biForest: + case biTaiga: + case biMegaTaiga: + case biColdTaiga: + case biColdTaigaM: + ListOfSpawnables.insert(MobIter, mtWolf); + + // All other mobs + default: + ListOfSpawnables.insert(MobIter, mtChicken); + ListOfSpawnables.insert(MobIter, mtCow); + ListOfSpawnables.insert(MobIter, mtPig); + ListOfSpawnables.insert(MobIter, mtSheep); } - if (ListOfSpawnables.size() == 0) + if (ListOfSpawnables.empty()) { - LOGD("Tried to spawn an animal from an empty list."); - return mtInvalidType; + return mtInvalidType; } int RandMob = m_Random.NextInt(ListOfSpawnables.size()); MobIter=ListOfSpawnables.begin(); for (int i = 0; i < RandMob; i++) { - ++MobIter; + ++MobIter; } return *MobIter; -- cgit v1.2.3 From 8d7c2d4b13c0a0903cc43d612dddcb10c12d7e21 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 11:26:37 -0800 Subject: fastRandom unused --- src/Generating/FinishGen.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index c8575f4d1..c4d2a0799 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -329,7 +329,6 @@ protected: cNoise m_Noise; int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk - cFastRandom m_Random; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; -- cgit v1.2.3 From 6803df129f6e197e4f45294d46002f6dd8469655 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 11:32:53 -0800 Subject: typos and oversights for lua and CI --- src/Generating/FinishGen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 3e5b24017..0844b01ab 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -986,6 +986,8 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) { + int chunkX = a_ChunkDesc.GetChunkX(); + int chunkZ = a_ChunkDesc.GetChunkZ(); int ChanceRnd = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % 100; if (ChanceRnd > m_AnimalProbability) { @@ -1074,6 +1076,8 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) std::set ListOfSpawnables; std::set::iterator MobIter = ListOfSpawnables.begin(); + int chunkX = a_ChunkDesc.GetChunkX(); + int chunkZ = a_ChunkDesc.GetChunkZ(); int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; int z = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; @@ -1137,7 +1141,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) return mtInvalidType; } - int RandMob = m_Random.NextInt(ListOfSpawnables.size()); + int RandMob = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % ListOfSpawnables.size(); MobIter=ListOfSpawnables.begin(); for (int i = 0; i < RandMob; i++) { -- cgit v1.2.3 From 2ea8a36df6bf0fd4d4eef21521ef0f07a87e895a Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 15:55:09 -0800 Subject: forgot initializer --- src/Generating/ComposableGenerator.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 6b8923955..bda45ad92 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -294,7 +294,11 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr) { // Finishers, alpha-sorted: - if (NoCaseCompare(*itr, "BottomLava") == 0) + if (NoCaseCompare(*itr, "Animals") == 0) + { + m_FinishGens.push_back(cFinishGenPtr(new cFinishGenPassiveMobs(Seed, a_IniFile, Dimension))); + } + else if (NoCaseCompare(*itr, "BottomLava") == 0) { int DefaultBottomLavaLevel = (Dimension == dimNether) ? 30 : 10; int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel); -- cgit v1.2.3 From d3484334064d950654bdf12ec0a81e1b860f627c Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Tue, 2 Dec 2014 22:35:34 -0800 Subject: doxy-commenting --- src/Generating/FinishGen.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index c4d2a0799..15dd70e15 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -310,7 +310,7 @@ protected: // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - /// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful + // Tries to place a spring at the specified coords, checks neighbors. Returns true if successful bool TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z); } ; @@ -333,10 +333,10 @@ protected: // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - // Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. + /** Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. */ bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); - // Gets a random mob from biome-dependant list + /** Gets a random mob from biome-dependant list */ eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); } ; -- cgit v1.2.3 From 8c3b9ae15b8c590610fb05f32bd19d2d480f3fd6 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Wed, 3 Dec 2014 00:12:32 -0800 Subject: class description and doxy-commenting --- src/Generating/FinishGen.cpp | 6 +++--- src/Generating/FinishGen.h | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 0844b01ab..d938c34bd 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1001,7 +1001,7 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) return; } - // Try spawning a pack center 10 times, should get roughly the same probability + /** Try spawning a pack center 10 times, should get roughly the same probability */ for (int Tries = 0; Tries < 10; Tries++) { int PackCenterX = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; @@ -1030,7 +1030,7 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ); BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); - // Check block below (opaque, grass, water), and above (air) + /** Check block below (opaque, grass, water), and above (air) */ if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) { return false; @@ -1081,7 +1081,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; int z = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; - // Check biomes first to get a list of animals + /** Check biomes first to get a list of animals */ switch (a_ChunkDesc.GetBiome(x, z)) { // No animals diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 15dd70e15..e11e6f414 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -318,6 +318,9 @@ protected: +/** This class populates generated chunks with packs of biome-dependant animals +Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots +*/ class cFinishGenPassiveMobs : public cFinishGen { @@ -328,9 +331,9 @@ public: protected: cNoise m_Noise; - int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk + int m_AnimalProbability; /** Chance, [0..100], that an animal pack will be generated in a chunk */ - // cFinishGen override: + /** cFinishGen override: */ virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; /** Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. */ -- cgit v1.2.3 From 27185dd3748b04af35a3d17eb5c2c58e826cd9cb Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Wed, 3 Dec 2014 00:26:15 -0800 Subject: clearing CheckBasicStyle.lua messages --- src/Generating/FinishGen.cpp | 26 +++++++++++++------------- src/Generating/FinishGen.h | 30 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index b9d702429..9e035926e 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -65,7 +65,7 @@ void cFinishGenNetherClumpFoliage::GenFinish(cChunkDesc & a_ChunkDesc) { continue; } - + // Choose what block to use. NOISE_DATATYPE BlockType = m_Noise.IntNoise3D((int) ChunkX, y, (int) ChunkZ); if (BlockType < -0.7) @@ -195,10 +195,10 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc) { continue; } - + // Get the top block + 1. This is the place where the grass would finaly be placed: int y = a_ChunkDesc.GetHeight(x, z) + 1; - + if (y >= 255) { continue; @@ -281,7 +281,7 @@ bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_ { return false; } - + // All conditions met, place a sugarcane here: a_ChunkDesc.SetBlockType(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_SUGARCANE); return true; @@ -294,7 +294,7 @@ bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) { // Generate small foliage (1-block): - + // TODO: Update heightmap with 1-block-tall foliage for (int z = 0; z < cChunkDef::Width; z++) { @@ -319,7 +319,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) // WEIRD, since we're using heightmap, so there should NOT be anything above it continue; } - + const float xx = (float)BlockX; float val1 = m_Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f); float val2 = m_Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f); @@ -359,7 +359,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) } break; } // case E_BLOCK_GRASS - + case E_BLOCK_SAND: { int y = Top + 1; @@ -400,7 +400,7 @@ void cFinishGenSoulsandRims::GenFinish(cChunkDesc & a_ChunkDesc) int ChunkZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); - for (int x = 0; x < 16; x++) + for (int x = 0; x < 16; x++) { int xx = ChunkX + x; for (int z = 0; z < 16; z++) @@ -768,7 +768,7 @@ void cFinishGenPreSimulator::StationarizeFluid( } // for y } // for x } // for z - + // Turn fluid at the chunk edges into non-stationary fluid: for (int y = 0; y < cChunkDef::Height; y++) { @@ -860,12 +860,12 @@ void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc) // Not in this chunk return; } - + // Get the height at which to try: int Height = m_Noise.IntNoise3DInt(128 * a_ChunkDesc.GetChunkX(), 1024, 256 * a_ChunkDesc.GetChunkZ()) / 11; Height %= m_HeightDistribution.GetSum(); Height = m_HeightDistribution.MapValue(Height); - + // Try adding the spring at the height, if unsuccessful, move lower: for (int y = Height; y > 1; y--) { @@ -903,7 +903,7 @@ bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int { return false; } - + static const struct { int x, y, z; @@ -934,7 +934,7 @@ bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int { return false; } - + // Has exactly one air neighbor, place a spring: a_ChunkDesc.SetBlockTypeMeta(x, y, z, m_Fluid, 0); return true; diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index d45365683..c1100b51f 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -121,7 +121,7 @@ class cFinishGenSoulsandRims : public cFinishGen { public: - cFinishGenSoulsandRims(int a_Seed) : + cFinishGenSoulsandRims(int a_Seed) : m_Noise(a_Seed) { } @@ -141,14 +141,14 @@ class cFinishGenSprinkleFoliage : { public: cFinishGenSprinkleFoliage(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {} - + protected: cNoise m_Noise; int m_Seed; - + /// Tries to place sugarcane at the coords specified, returns true if successful bool TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ); - + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; @@ -186,31 +186,31 @@ public: { m_IsAllowedBelow[idx] = false; } - + // Load the allowed blocks into m_IsAllowedBelow for (BlockList::iterator itr = a_AllowedBelow.begin(); itr != a_AllowedBelow.end(); ++itr) { m_IsAllowedBelow[*itr] = true; } - + // Initialize all the biome types. for (size_t idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) { m_IsBiomeAllowed[idx] = false; } - + // Load the allowed biomes into m_IsBiomeAllowed for (BiomeList::iterator itr = a_Biomes.begin(); itr != a_Biomes.end(); ++itr) { m_IsBiomeAllowed[*itr] = true; } } - + protected: cNoise m_Noise; BLOCKTYPE m_BlockType; int m_Amount; ///< Relative amount of blocks to try adding. 1 = one block per 256 biome columns. - + int GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap); // Returns true if the given biome is a biome that is allowed. @@ -225,7 +225,7 @@ protected: return m_IsAllowedBelow[a_BlockBelow]; } - + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; @@ -242,11 +242,11 @@ public: m_Level(a_Level) { } - + int GetLevel(void) const { return m_Level; } protected: int m_Level; - + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; @@ -260,7 +260,7 @@ class cFinishGenPreSimulator : { public: cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava); - + protected: bool m_PreSimulateFallingBlocks; @@ -272,7 +272,7 @@ protected: cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change cChunkDef::HeightMap & a_HeightMap // Height map to update by the current data ); - + /** For each fluid block: - if all surroundings are of the same fluid, makes it stationary; otherwise makes it flowing (excl. top) - all fluid on the chunk's edge is made flowing @@ -297,7 +297,7 @@ class cFinishGenFluidSprings : { public: cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, eDimension a_Dimension); - + protected: cNoise m_Noise; -- cgit v1.2.3 From 83d4bec369643c82c3f13e2e1c6d13009a2a0bd9 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 01:08:17 -0800 Subject: awful comment fixing, randomizer fix --- src/Generating/FinishGen.cpp | 35 ++++++++++++++++++++++++----------- src/Generating/FinishGen.h | 16 ++++++++-------- 2 files changed, 32 insertions(+), 19 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index d938c34bd..e9cdfe91e 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -974,7 +974,7 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e } } // switch (dimension) m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); - if (m_AnimalProbability < 0 || m_AnimalProbability > 100) + if ((m_AnimalProbability < 0) || (m_AnimalProbability > 100)) { LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); } @@ -1001,7 +1001,7 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) return; } - /** Try spawning a pack center 10 times, should get roughly the same probability */ + // Try spawning a pack center 10 times, should get roughly the same probability for (int Tries = 0; Tries < 10; Tries++) { int PackCenterX = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; @@ -1010,8 +1010,8 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) { for (int i = 0; i < 5; i++) { - int OffsetX = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; - int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; + int OffsetX = (m_Noise.IntNoise2DInt(chunkX + chunkZ, Tries) / 7) % cChunkDef::Width; + int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries) / 7) % cChunkDef::Width; TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); } return; @@ -1026,11 +1026,16 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, eMonsterType AnimalToSpawn) { + if ((a_RelY >= cChunkDef::Height - 1) || (a_RelY <= 0)) + { + return false; + } + BLOCKTYPE BlockAtHead = a_ChunkDesc.GetBlockType(a_RelX, a_RelY + 1, a_RelZ); BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ); BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); - /** Check block below (opaque, grass, water), and above (air) */ + // Check block below (opaque, grass, water), and above (air) if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) { return false; @@ -1087,53 +1092,61 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) // No animals case biNether: case biEnd: + { return mtInvalidType; - + } // Squid only case biOcean: case biFrozenOcean: case biFrozenRiver: case biRiver: case biDeepOcean: + { ListOfSpawnables.insert(MobIter, mtSquid); break; - + } // Mooshroom only case biMushroomIsland: case biMushroomShore: + { ListOfSpawnables.insert(MobIter, mtMooshroom); break; - + } case biJungle: case biJungleHills: case biJungleEdge: case biJungleM: case biJungleEdgeM: + { ListOfSpawnables.insert(MobIter, mtOcelot); - + } case biPlains: case biSunflowerPlains: case biSavanna: case biSavannaPlateau: case biSavannaM: case biSavannaPlateauM: + { ListOfSpawnables.insert(MobIter, mtHorse); // ListOfSpawnables.insert(mtDonkey); - + } // Wolves only case biForest: case biTaiga: case biMegaTaiga: case biColdTaiga: case biColdTaigaM: + { ListOfSpawnables.insert(MobIter, mtWolf); - + } // All other mobs default: + { ListOfSpawnables.insert(MobIter, mtChicken); ListOfSpawnables.insert(MobIter, mtCow); ListOfSpawnables.insert(MobIter, mtPig); ListOfSpawnables.insert(MobIter, mtSheep); + } } if (ListOfSpawnables.empty()) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index e11e6f414..1866d6133 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -318,28 +318,28 @@ protected: -/** This class populates generated chunks with packs of biome-dependant animals -Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots -*/ class cFinishGenPassiveMobs : public cFinishGen { public: - + + /** This class populates generated chunks with packs of biome-dependant animals + Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots + */ cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension); protected: cNoise m_Noise; - int m_AnimalProbability; /** Chance, [0..100], that an animal pack will be generated in a chunk */ + int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk - /** cFinishGen override: */ + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - /** Tries to spawn a mob in the center of the pack. If successful, spawns 0-5 more. */ + // Returns false if an animal cannot spawn at given coords, else adds it to the chunk's entity list and returns true bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); - /** Gets a random mob from biome-dependant list */ + // Gets a random animal from biome-dependant list eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); } ; -- cgit v1.2.3 From b7c4ef05ac320428cfa2fdeed562302f78d1a7ab Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 01:18:55 -0800 Subject: last doxy fix --- src/Generating/FinishGen.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 1866d6133..f2b59fa08 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -318,14 +318,14 @@ protected: +/** This class populates generated chunks with packs of biome-dependant animals + Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots + */ class cFinishGenPassiveMobs : public cFinishGen { public: - /** This class populates generated chunks with packs of biome-dependant animals - Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots - */ cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension); protected: -- cgit v1.2.3 From 99a5b38e27647e4535eed53b7b6d9cc6ea74c538 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 13:28:27 -0800 Subject: format blocks and randomizing --- src/Generating/FinishGen.cpp | 17 +++++++++-------- src/Generating/FinishGen.h | 1 - 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index e9cdfe91e..e72e91c85 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1004,14 +1004,14 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) // Try spawning a pack center 10 times, should get roughly the same probability for (int Tries = 0; Tries < 10; Tries++) { - int PackCenterX = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; - int PackCenterZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; + int PackCenterX = (m_Noise.IntNoise2DInt(chunkX + chunkZ, Tries) / 7) % cChunkDef::Width; + int PackCenterZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries) / 7) % cChunkDef::Width; if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) { for (int i = 0; i < 5; i++) { - int OffsetX = (m_Noise.IntNoise2DInt(chunkX + chunkZ, Tries) / 7) % cChunkDef::Width; - int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries) / 7) % cChunkDef::Width; + int OffsetX = (m_Noise.IntNoise2DInt(chunkX + chunkZ + i, Tries) / 7) % cChunkDef::Width; + int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries + i) / 7) % cChunkDef::Width; TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); } return; @@ -1040,7 +1040,8 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX { return false; } - if ((AnimalToSpawn != mtSquid) && + if ( + (AnimalToSpawn != mtSquid) && (BlockAtHead != E_BLOCK_AIR) && (BlockAtFeet != E_BLOCK_AIR) && (!cBlockInfo::IsTransparent(BlockUnderFeet)) @@ -1083,8 +1084,8 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) std::set::iterator MobIter = ListOfSpawnables.begin(); int chunkX = a_ChunkDesc.GetChunkX(); int chunkZ = a_ChunkDesc.GetChunkZ(); - int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; - int z = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % cChunkDef::Width; + int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ + 10) / 7) % cChunkDef::Width; + int z = (m_Noise.IntNoise2DInt(chunkX + chunkZ, chunkZ) / 7) % cChunkDef::Width; /** Check biomes first to get a list of animals */ switch (a_ChunkDesc.GetBiome(x, z)) @@ -1154,7 +1155,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) return mtInvalidType; } - int RandMob = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % ListOfSpawnables.size(); + int RandMob = (m_Noise.IntNoise2DInt(chunkX - chunkZ + 2, chunkX + 5) / 7) % ListOfSpawnables.size(); MobIter=ListOfSpawnables.begin(); for (int i = 0; i < RandMob; i++) { diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index f2b59fa08..600a506bc 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -19,7 +19,6 @@ #include "../Noise/Noise.h" #include "../ProbabDistrib.h" #include "../Mobs/Monster.h" -#include "FastRandom.h" -- cgit v1.2.3 From 53a33595b7c53d3728cc38627a3d0601fce735aa Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 16:44:18 -0800 Subject: formatting fixes --- src/Generating/FinishGen.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index e72e91c85..e50942073 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1049,12 +1049,14 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX { return false; } - if ((BlockUnderFeet != E_BLOCK_GRASS) && - ((AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig))) + if ( + (BlockUnderFeet != E_BLOCK_GRASS) && + ((AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig)) + ) { return false; } - if (AnimalToSpawn == mtMooshroom && BlockUnderFeet != E_BLOCK_MYCELIUM) + if ((AnimalToSpawn == mtMooshroom) && (BlockUnderFeet != E_BLOCK_MYCELIUM)) { return false; } @@ -1150,13 +1152,18 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) } } + ListOfSpawnables.insert(MobIter, mtChicken); + ListOfSpawnables.insert(MobIter, mtCow); + ListOfSpawnables.insert(MobIter, mtPig); + ListOfSpawnables.insert(MobIter, mtSheep); + if (ListOfSpawnables.empty()) { return mtInvalidType; } int RandMob = (m_Noise.IntNoise2DInt(chunkX - chunkZ + 2, chunkX + 5) / 7) % ListOfSpawnables.size(); - MobIter=ListOfSpawnables.begin(); + MobIter = ListOfSpawnables.begin(); for (int i = 0; i < RandMob; i++) { ++MobIter; -- cgit v1.2.3 From 538991c973fc6839b16b48b40a22084fe1218f74 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 16:59:45 -0800 Subject: handle non-vanilla dimensions --- src/Generating/FinishGen.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index e50942073..c83dfec67 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -835,6 +835,7 @@ cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cI default: { ASSERT(!"Unhandled world dimension"); + DefaultChance = 0; break; } } // switch (dimension) @@ -970,7 +971,7 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e default: { ASSERT(!"Unhandled world dimension"); - break; + return; } } // switch (dimension) m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); @@ -1156,7 +1157,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) ListOfSpawnables.insert(MobIter, mtCow); ListOfSpawnables.insert(MobIter, mtPig); ListOfSpawnables.insert(MobIter, mtSheep); - + if (ListOfSpawnables.empty()) { return mtInvalidType; -- cgit v1.2.3 From 78f0aebaf4bdef13d2cc61880111365297723517 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 17:01:34 -0800 Subject: handle non-vanilla dimensions --- src/Generating/FinishGen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index c83dfec67..a34f61fcf 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -835,7 +835,6 @@ cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cI default: { ASSERT(!"Unhandled world dimension"); - DefaultChance = 0; break; } } // switch (dimension) @@ -971,7 +970,8 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e default: { ASSERT(!"Unhandled world dimension"); - return; + DefaultChance = 0; + break; } } // switch (dimension) m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); -- cgit v1.2.3 From bd8c1850da9c80ae59334fd96da51c624893aac4 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Thu, 4 Dec 2014 17:20:19 -0800 Subject: restructured random animals, added check for desert (update as per wiki) --- src/Generating/FinishGen.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index a34f61fcf..97ee5a9f9 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -970,7 +970,7 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e default: { ASSERT(!"Unhandled world dimension"); - DefaultChance = 0; + DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; break; } } // switch (dimension) @@ -1009,7 +1009,7 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) int PackCenterZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries) / 7) % cChunkDef::Width; if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) { - for (int i = 0; i < 5; i++) + for (int i = 0; i < 3; i++) { int OffsetX = (m_Noise.IntNoise2DInt(chunkX + chunkZ + i, Tries) / 7) % cChunkDef::Width; int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries + i) / 7) % cChunkDef::Width; @@ -1093,13 +1093,23 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) /** Check biomes first to get a list of animals */ switch (a_ChunkDesc.GetBiome(x, z)) { - // No animals + // No animals in deserts or non-overworld dimensions case biNether: case biEnd: + case biDesertHills: + case biDesert: + case biDesertM: { return mtInvalidType; } - // Squid only + // Mooshroom only - no other mobs on mushroom islands + case biMushroomIsland: + case biMushroomShore: + { + ListOfSpawnables.insert(MobIter, mtMooshroom); + break; + } + // Add squid in ocean biomes case biOcean: case biFrozenOcean: case biFrozenRiver: @@ -1107,15 +1117,8 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biDeepOcean: { ListOfSpawnables.insert(MobIter, mtSquid); - break; - } - // Mooshroom only - case biMushroomIsland: - case biMushroomShore: - { - ListOfSpawnables.insert(MobIter, mtMooshroom); - break; } + // Add ocelots in jungle biomes case biJungle: case biJungleHills: case biJungleEdge: @@ -1134,7 +1137,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) ListOfSpawnables.insert(MobIter, mtHorse); // ListOfSpawnables.insert(mtDonkey); } - // Wolves only + // Add wolves in forest and spruce forests case biForest: case biTaiga: case biMegaTaiga: @@ -1143,7 +1146,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) { ListOfSpawnables.insert(MobIter, mtWolf); } - // All other mobs + // All other animals can be added to the list default: { ListOfSpawnables.insert(MobIter, mtChicken); @@ -1153,11 +1156,6 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) } } - ListOfSpawnables.insert(MobIter, mtChicken); - ListOfSpawnables.insert(MobIter, mtCow); - ListOfSpawnables.insert(MobIter, mtPig); - ListOfSpawnables.insert(MobIter, mtSheep); - if (ListOfSpawnables.empty()) { return mtInvalidType; -- cgit v1.2.3 From c655d97c9db9408dc178f436baa87d894363ecb3 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Fri, 5 Dec 2014 00:57:40 -0800 Subject: restructure, with logic this time --- src/Generating/FinishGen.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 97ee5a9f9..6788afca3 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1117,6 +1117,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biDeepOcean: { ListOfSpawnables.insert(MobIter, mtSquid); + break; } // Add ocelots in jungle biomes case biJungle: @@ -1126,6 +1127,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biJungleEdgeM: { ListOfSpawnables.insert(MobIter, mtOcelot); + break; } case biPlains: case biSunflowerPlains: @@ -1136,6 +1138,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) { ListOfSpawnables.insert(MobIter, mtHorse); // ListOfSpawnables.insert(mtDonkey); + break; } // Add wolves in forest and spruce forests case biForest: @@ -1145,16 +1148,21 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biColdTaigaM: { ListOfSpawnables.insert(MobIter, mtWolf); + break; } - // All other animals can be added to the list + // Nothing special about this biome default: { - ListOfSpawnables.insert(MobIter, mtChicken); - ListOfSpawnables.insert(MobIter, mtCow); - ListOfSpawnables.insert(MobIter, mtPig); - ListOfSpawnables.insert(MobIter, mtSheep); + break; } } + if ((a_ChunkDesc.GetBiome(x, z) != biMushroomIsland) && (a_ChunkDesc.GetBiome(x, z) != biMushroomShore)) + { + ListOfSpawnables.insert(MobIter, mtChicken); + ListOfSpawnables.insert(MobIter, mtCow); + ListOfSpawnables.insert(MobIter, mtPig); + ListOfSpawnables.insert(MobIter, mtSheep); + } if (ListOfSpawnables.empty()) { -- cgit v1.2.3 From 750b4a3eaadab231cd215cbc8557ad67a67742cc Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Fri, 5 Dec 2014 01:01:10 -0800 Subject: reformat --- src/Generating/FinishGen.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 6788afca3..358ed16a1 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1106,8 +1106,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biMushroomIsland: case biMushroomShore: { - ListOfSpawnables.insert(MobIter, mtMooshroom); - break; + return mtMooshroom; } // Add squid in ocean biomes case biOcean: @@ -1156,13 +1155,10 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) break; } } - if ((a_ChunkDesc.GetBiome(x, z) != biMushroomIsland) && (a_ChunkDesc.GetBiome(x, z) != biMushroomShore)) - { - ListOfSpawnables.insert(MobIter, mtChicken); - ListOfSpawnables.insert(MobIter, mtCow); - ListOfSpawnables.insert(MobIter, mtPig); - ListOfSpawnables.insert(MobIter, mtSheep); - } + ListOfSpawnables.insert(MobIter, mtChicken); + ListOfSpawnables.insert(MobIter, mtCow); + ListOfSpawnables.insert(MobIter, mtPig); + ListOfSpawnables.insert(MobIter, mtSheep); if (ListOfSpawnables.empty()) { -- cgit v1.2.3 From e2a04f580a0813206f527a61244cb3382248fd12 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 5 Dec 2014 16:59:11 +0100 Subject: BasicStyle: Added missing braces to control statements. --- src/Generating/Caves.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp index fc925a150..e4735cb83 100644 --- a/src/Generating/Caves.cpp +++ b/src/Generating/Caves.cpp @@ -692,8 +692,14 @@ static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise) float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f)) * 4; oct1 = oct1 * oct1 * oct1; - if (oct1 < 0.f) oct1 = PI_2; - if (oct1 > PI_2) oct1 = PI_2; + if (oct1 < 0.f) + { + oct1 = PI_2; + } + if (oct1 > PI_2) + { + oct1 = PI_2; + } return oct1; } -- cgit v1.2.3 From b25fcb0972554facbd4dfd79cb256a77a2cb6773 Mon Sep 17 00:00:00 2001 From: p-mcgowan Date: Fri, 5 Dec 2014 11:31:01 -0800 Subject: formatting and default spawn percentage --- src/Generating/FinishGen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 41dbdca16..ad3dc5293 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -993,6 +993,7 @@ cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, e if ((m_AnimalProbability < 0) || (m_AnimalProbability > 100)) { LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); + m_AnimalProbability = DefaultAnimalSpawnChunkPercentage; } } @@ -1052,7 +1053,7 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); // Check block below (opaque, grass, water), and above (air) - if (AnimalToSpawn == mtSquid && BlockAtFeet != E_BLOCK_WATER) + if ((AnimalToSpawn == mtSquid) && (BlockAtFeet != E_BLOCK_WATER)) { return false; } -- cgit v1.2.3 From c5dc5ac45f19aac55f99629603cfaf81ac3d0b10 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 5 Dec 2014 22:46:46 +0100 Subject: FinishGenPassiveMobs: Cosmetic changes. --- src/Generating/FinishGen.cpp | 45 ++++++++++++++++++++++---------------------- src/Generating/FinishGen.h | 18 +++++++++++------- 2 files changed, 33 insertions(+), 30 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index ad3dc5293..e6732dbd5 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1078,16 +1078,14 @@ bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX return false; } - int AnimalX, AnimalY, AnimalZ; - AnimalX = (double)(a_ChunkDesc.GetChunkX()*cChunkDef::Width + a_RelX + 0.5); - AnimalY = a_RelY; - AnimalZ = (double)(a_ChunkDesc.GetChunkZ()*cChunkDef::Width + a_RelZ + 0.5); + double AnimalX = static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX + 0.5); + double AnimalY = a_RelY; + double AnimalZ = static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ + 0.5); - cEntityList ChunkEntities = a_ChunkDesc.GetEntities(); cMonster * NewMob = cMonster::NewMonsterFromType(AnimalToSpawn); NewMob->SetPosition(AnimalX, AnimalY, AnimalZ); - ChunkEntities.push_back(NewMob); - LOGD("Spawning %s #%i at {%d, %d, %d}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ); + a_ChunkDesc.GetEntities().push_back(NewMob); + LOGD("Spawning %s #%i at {%.02f, %.02f, %.02f}", NewMob->GetClass(), NewMob->GetUniqueID(), AnimalX, AnimalY, AnimalZ); return true; } @@ -1100,13 +1098,12 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) { std::set ListOfSpawnables; - std::set::iterator MobIter = ListOfSpawnables.begin(); int chunkX = a_ChunkDesc.GetChunkX(); int chunkZ = a_ChunkDesc.GetChunkZ(); int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ + 10) / 7) % cChunkDef::Width; int z = (m_Noise.IntNoise2DInt(chunkX + chunkZ, chunkZ) / 7) % cChunkDef::Width; - /** Check biomes first to get a list of animals */ + // Check biomes first to get a list of animals switch (a_ChunkDesc.GetBiome(x, z)) { // No animals in deserts or non-overworld dimensions @@ -1118,12 +1115,14 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) { return mtInvalidType; } + // Mooshroom only - no other mobs on mushroom islands case biMushroomIsland: case biMushroomShore: { return mtMooshroom; } + // Add squid in ocean biomes case biOcean: case biFrozenOcean: @@ -1131,9 +1130,10 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biRiver: case biDeepOcean: { - ListOfSpawnables.insert(MobIter, mtSquid); + ListOfSpawnables.insert(mtSquid); break; } + // Add ocelots in jungle biomes case biJungle: case biJungleHills: @@ -1141,9 +1141,11 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biJungleM: case biJungleEdgeM: { - ListOfSpawnables.insert(MobIter, mtOcelot); + ListOfSpawnables.insert(mtOcelot); break; } + + // Add horses in plains-like biomes case biPlains: case biSunflowerPlains: case biSavanna: @@ -1151,10 +1153,10 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biSavannaM: case biSavannaPlateauM: { - ListOfSpawnables.insert(MobIter, mtHorse); - // ListOfSpawnables.insert(mtDonkey); + ListOfSpawnables.insert(mtHorse); break; } + // Add wolves in forest and spruce forests case biForest: case biTaiga: @@ -1162,7 +1164,7 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) case biColdTaiga: case biColdTaigaM: { - ListOfSpawnables.insert(MobIter, mtWolf); + ListOfSpawnables.insert(mtWolf); break; } // Nothing special about this biome @@ -1171,10 +1173,10 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) break; } } - ListOfSpawnables.insert(MobIter, mtChicken); - ListOfSpawnables.insert(MobIter, mtCow); - ListOfSpawnables.insert(MobIter, mtPig); - ListOfSpawnables.insert(MobIter, mtSheep); + ListOfSpawnables.insert(mtChicken); + ListOfSpawnables.insert(mtCow); + ListOfSpawnables.insert(mtPig); + ListOfSpawnables.insert(mtSheep); if (ListOfSpawnables.empty()) { @@ -1182,11 +1184,8 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) } int RandMob = (m_Noise.IntNoise2DInt(chunkX - chunkZ + 2, chunkX + 5) / 7) % ListOfSpawnables.size(); - MobIter = ListOfSpawnables.begin(); - for (int i = 0; i < RandMob; i++) - { - ++MobIter; - } + auto MobIter = ListOfSpawnables.begin(); + std::advance(MobIter, RandMob); return *MobIter; } diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 8305908c0..ae6dee590 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -312,7 +312,7 @@ protected: // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - // Tries to place a spring at the specified coords, checks neighbors. Returns true if successful + /** Tries to place a spring at the specified coords, checks neighbors. Returns true if successful. */ bool TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z); } ; @@ -321,8 +321,7 @@ protected: /** This class populates generated chunks with packs of biome-dependant animals - Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots - */ +Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots */ class cFinishGenPassiveMobs : public cFinishGen { @@ -332,16 +331,21 @@ public: protected: - cNoise m_Noise; - int m_AnimalProbability; // Chance, [0..100], that an animal pack will be generated in a chunk + /** The noise used as the source of randomness */ + cNoise m_Noise; + + /** Chance, [0..100], that an animal pack will be generated in a chunk */ + int m_AnimalProbability; + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - // Returns false if an animal cannot spawn at given coords, else adds it to the chunk's entity list and returns true + /** Returns false if an animal cannot spawn at given coords, else adds it to the chunk's entity list and returns true */ bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); - // Gets a random animal from biome-dependant list + /** Picks a random animal from biome-dependant list for a random position in the chunk. + Returns the chosen mob type, or mtInvalid if no mob chosen. */ eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); } ; -- cgit v1.2.3 From 95c83abcdb11d285ef409a6ed8900985927e9de0 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 7 Dec 2014 12:00:36 +0100 Subject: Fixed error message in cFinishGenPassiveMobs It would send an error message when trying to spawn mobs in a desert --- src/Generating/FinishGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Generating') diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index e6732dbd5..e10cb00f8 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1014,7 +1014,7 @@ void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) eMonsterType RandomMob = GetRandomMob(a_ChunkDesc); if (RandomMob == mtInvalidType) { - LOGWARNING("Attempted to spawn invalid mob type."); + // No mobs here. Don't send an error, because if the biome was a desert it would return mtInvalidType as well. return; } -- cgit v1.2.3 From ba991075910abca0f512c7a77d1fc6af412b1f4d Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 7 Dec 2014 12:03:52 +0100 Subject: Reduced river height Rivers would exceed the water height quite often --- src/Generating/Noise3DGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index 57e23809e..5ed97a945 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -739,7 +739,7 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; - case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 57; break; + case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 54; break; case biFrozenOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; @@ -764,7 +764,7 @@ void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE case biNether: a_HeightAmp = 0.01f; a_MidPoint = 64; break; case biOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; - case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 57; break; + case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 54; break; case biRoofedForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biRoofedForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biSavanna: a_HeightAmp = 0.3f; a_MidPoint = 62; break; -- cgit v1.2.3 From fcd3d1bfedbfbe535f406e3db933486bad913ab4 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 10 Dec 2014 22:35:16 +0100 Subject: Added a cWorld:PrepareChunk function. It prepares the chunk - loads or generates it and lights it. The spawn prepare process uses this function. --- src/Generating/ChunkGenerator.cpp | 47 +++++++++++++++++++++------------------ src/Generating/ChunkGenerator.h | 47 +++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 31 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index d2e7b47b4..854aac60d 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -110,29 +110,19 @@ void cChunkGenerator::Stop(void) -void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate) +void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate, cChunkCoordCallback * a_Callback) { ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ)); { cCSLock Lock(m_CS); - // Check if it is already in the queue: - for (cChunkCoordsWithBoolList::iterator itr = m_Queue.begin(); itr != m_Queue.end(); ++itr) - { - if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ)) - { - // Already in the queue, bail out - return; - } - } // for itr - m_Queue[] - // Add to queue, issue a warning if too many: if (m_Queue.size() >= QUEUE_WARNING_LIMIT) { LOGWARN("WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (" SIZE_T_FMT ")", a_ChunkX, a_ChunkZ, m_Queue.size()); } - m_Queue.push_back(cChunkCoordsWithBool(a_ChunkX, a_ChunkZ, a_ForceGenerate)); + m_Queue.push_back(cQueueItem{a_ChunkX, a_ChunkZ, a_ForceGenerate, a_Callback}); } m_Event.Set(); @@ -242,9 +232,9 @@ void cChunkGenerator::Execute(void) continue; } - cChunkCoordsWithBool coords = m_Queue.front(); // Get next coord from queue + cQueueItem item = m_Queue.front(); // Get next chunk from the queue bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT); - m_Queue.erase(m_Queue.begin()); // Remove coordinate from queue + m_Queue.erase(m_Queue.begin()); // Remove the item from the queue Lock.Unlock(); // Unlock ASAP m_evtRemoved.Set(); @@ -258,22 +248,35 @@ void cChunkGenerator::Execute(void) LastReportTick = clock(); } - if (!coords.m_ForceGenerate && m_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ)) + // Skip the chunk if it's already generated and regeneration is not forced: + if (!item.m_ForceGenerate && m_ChunkSink->IsChunkValid(item.m_ChunkX, item.m_ChunkZ)) { - LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ); - // Already generated, ignore request + LOGD("Chunk [%d, %d] already generated, skipping generation", item.m_ChunkX, item.m_ChunkZ); + if (item.m_Callback != nullptr) + { + item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ); + } continue; } - if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkZ)) + // Skip the chunk if the generator is overloaded: + if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(item.m_ChunkX, item.m_ChunkZ)) { - LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ); + LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", item.m_ChunkX, item.m_ChunkZ); + if (item.m_Callback != nullptr) + { + item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ); + } continue; } - LOGD("Generating chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ); - DoGenerate(coords.m_ChunkX, coords.m_ChunkZ); - + // Generate the chunk: + LOGD("Generating chunk [%d, %d]", item.m_ChunkX, item.m_ChunkZ); + DoGenerate(item.m_ChunkX, item.m_ChunkZ); + if (item.m_Callback != nullptr) + { + item.m_Callback->Call(item.m_ChunkX, item.m_ChunkZ); + } NumChunksGenerated++; } // while (!bStop) } diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h index 190d9e616..4af486ae1 100644 --- a/src/Generating/ChunkGenerator.h +++ b/src/Generating/ChunkGenerator.h @@ -119,8 +119,12 @@ public: bool Start(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile); void Stop(void); - /// Queues the chunk for generation; removes duplicate requests - void QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate); + /** Queues the chunk for generation + If a-ForceGenerate is set, the chunk is regenerated even if the data is already present in the chunksink. + a_Callback is called after the chunk is generated. If the chunk was already present, the callback is still called, even if not regenerating. + 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); @@ -131,22 +135,46 @@ public: 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 + /** 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. + /** 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 + { + /** The chunk coords */ + int m_ChunkX, m_ChunkZ; + + /** Force the regeneration of an already existing chunk */ + bool m_ForceGenerate; + + /** Callback to call after generating.*/ + cChunkCoordCallback * m_Callback; + }; + + typedef std::list cGenQueue; + + + /** Seed used for the generator. */ int m_Seed; - cCriticalSection m_CS; - cChunkCoordsWithBoolList m_Queue; - cEvent m_Event; ///< Set when an item is added to the queue or the thread should terminate - cEvent m_evtRemoved; ///< Set when an item is removed from the queue + /** CS protecting access to the queue. */ + cCriticalSection m_CS; + + /** Queue of the chunks to be generated. Protected against multithreaded access by m_CS. */ + cGenQueue m_Queue; + + /** Set when an item is added to the queue or the thread should terminate. */ + cEvent m_Event; + + /** Set when an item is removed from the queue. */ + cEvent m_evtRemoved; - cGenerator * m_Generator; ///< The actual generator engine used to generate chunks + /** The actual generator engine used to generate chunks. */ + cGenerator * m_Generator; /** The plugin interface that may modify the generated chunks */ cPluginInterface * m_PluginInterface; @@ -158,6 +186,7 @@ private: // cIsThread override: virtual void Execute(void) override; + /** Generates the specified chunk and sets it into the chunksink. */ void DoGenerate(int a_ChunkX, int a_ChunkZ); }; -- cgit v1.2.3 From 09453619e6e1e8589424017761f753f16ce7842d Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 11 Dec 2014 11:16:11 +0100 Subject: Fixed DungeonRooms edges not generating sometimes. --- src/Generating/DungeonRoomsFinisher.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp index 092e232ab..c4bf8839e 100644 --- a/src/Generating/DungeonRoomsFinisher.cpp +++ b/src/Generating/DungeonRoomsFinisher.cpp @@ -131,8 +131,8 @@ protected: { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; - int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1); - int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1); + int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width); + int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width); int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width); int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width); for (int y = a_StartY; y < a_EndY; y++) -- cgit v1.2.3