// 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 { using Super = cTerrainShapeGen; public: cTwoHeights(int a_Seed, cBiomeGen & 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(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override { // Generate the two heightmaps: cChunkDef::HeightMap heightsA; cChunkDef::HeightMap heightsB; m_HeightA.GenHeightMap(a_ChunkCoords, heightsA); m_HeightB.GenHeightMap(a_ChunkCoords, 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_ChunkCoords.m_ChunkX * cChunkDef::Width * m_FrequencyX; NOISE_DATATYPE endY = (a_ChunkCoords.m_ChunkX * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyX; NOISE_DATATYPE startZ = a_ChunkCoords.m_ChunkZ * cChunkDef::Width * m_FrequencyZ; NOISE_DATATYPE endZ = (a_ChunkCoords.m_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) override { 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; }; std::unique_ptr CreateShapeGenTwoHeights(int a_Seed, cBiomeGen & a_BiomeGen) { return std::make_unique(a_Seed, a_BiomeGen); }