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::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::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 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); }
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 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 biExtremeHillsPlus: case biExtremeHills: { // Select the pattern to use - 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.1) ? patStone.Get() : patGrass.Get(); FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern); 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.9) ? patStone.Get() : ((Val > 0) ? patGravel.Get() : patGrass.Get()); FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern); return; } default: { ASSERT(!"Unhandled biome"); return; } } // switch (Biome) }
/** 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); EMCSBiome MesaVersion = a_ChunkDesc.GetBiome(a_RelX, a_RelZ); if ((MesaVersion == biMesaPlateauF) || (MesaVersion == biMesaPlateauFM)) { if (Top < 95 + static_cast<int>(m_MesaFloor.CubicNoise2D(NoiseY * 2, NoiseX * 2) * 6)) { return; } BLOCKTYPE Block = (m_MesaFloor.CubicNoise2D(NoiseX * 4, NoiseY * 4) < 0) ? E_BLOCK_DIRT : E_BLOCK_GRASS; NIBBLETYPE Meta = (Block == E_BLOCK_GRASS) ? 0 : 1; a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, Block, Meta); } }