/** 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; HEIGHTTYPE 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); }
void cDistortedHeightmap::FillColumnPattern(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const sBlockInfo * a_Pattern) { int NoiseArrayIdx = a_RelX + 17 * 257 * a_RelZ; bool HasHadWater = false; int PatternIdx = 0; for (int y = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); y > 0; y--) { int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y]; if (y < HeightMapHeight) { // "ground" part, use the pattern: a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[PatternIdx].BlockType, a_Pattern[PatternIdx].BlockMeta); PatternIdx++; continue; } // "air" or "water" part: // Reset the pattern index to zero, so that the pattern is repeated from the top again: PatternIdx = 0; if (y >= m_SeaLevel) { // "air" part, do nothing continue; } a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); if (HasHadWater) { continue; } // Select the ocean-floor pattern to use: a_Pattern = ChooseOceanFloorPattern(a_RelX, a_RelZ); HasHadWater = true; } // for y a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); }
void cDistortedHeightmap::FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ) { // Frequencies for the clay floor noise: const NOISE_DATATYPE FrequencyX = 50; const NOISE_DATATYPE FrequencyZ = 50; int Top = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); if (Top < m_SeaLevel) { // The terrain is below sealevel, handle as regular ocean: FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patOFRedSand.Get()); return; } NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ; int ClayFloor = m_SeaLevel - 6 + (int)(4.f * m_MesaFloor.CubicNoise2D(NoiseX, NoiseY)); if (ClayFloor >= Top) { ClayFloor = Top - 1; } if (Top - m_SeaLevel < 5) { // Simple case: top is red sand, then hardened clay down to ClayFloor, then stone: a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, E_BLOCK_SAND, E_META_SAND_RED); for (int y = Top - 1; y >= ClayFloor; y--) { a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_HARDENED_CLAY); } for (int y = ClayFloor - 1; y > 0; y--) { a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); } a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); return; } // Difficult case: use the mesa pattern and watch for overhangs: int NoiseArrayIdx = a_RelX + 17 * 257 * a_RelZ; int PatternIdx = cChunkDef::Height - (Top - ClayFloor); // We want the block at index ClayFloor to be pattern's 256th block (first stone) const sBlockInfo * Pattern = m_MesaPattern; bool HasHadWater = false; for (int y = Top; y > 0; y--) { int HeightMapHeight = (int)m_DistortedHeightmap[NoiseArrayIdx + 17 * y]; if (y < HeightMapHeight) { // "ground" part, use the pattern: a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, Pattern[PatternIdx].BlockType, Pattern[PatternIdx].BlockMeta); PatternIdx++; continue; } if (y >= m_SeaLevel) { // "air" part, do nothing continue; } // "water" part, fill with water and choose new pattern for ocean floor, if not chosen already: PatternIdx = 0; a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); if (HasHadWater) { continue; } // Select the ocean-floor pattern to use: Pattern = ChooseOceanFloorPattern(a_RelX, a_RelZ); HasHadWater = true; } // for y a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); }
/** 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); } }