From 76a92a21d11265ad17dffd11101ea87ce5c60e6a Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sat, 18 Feb 2012 19:18:16 +0000 Subject: Re-implemented tree-growing. May produce artefacts on old-world / new-world boundaries. git-svn-id: http://mc-server.googlecode.com/svn/trunk@293 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cWorldGenerator.cpp | 221 ++++++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 93 deletions(-) (limited to 'source/cWorldGenerator.cpp') diff --git a/source/cWorldGenerator.cpp b/source/cWorldGenerator.cpp index 284b4c478..b1f868cad 100644 --- a/source/cWorldGenerator.cpp +++ b/source/cWorldGenerator.cpp @@ -14,6 +14,27 @@ +// An array describing an 8-way neighbor coords deltas +static struct +{ + int m_X; + int m_Z; +} g_NeighborCoords[] = +{ + {-1, -1}, + {-1, 0}, + {-1, 1}, + {0, -1}, + {0, 1}, + {1, -1}, + {1, 0}, + {1, 1}, +} ; + + + + + cWorldGenerator::cWorldGenerator(cWorld * a_World) : m_World(a_World) { @@ -40,6 +61,46 @@ void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, ch +void cWorldGenerator::PostGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + // Check the chunk just generated and all its 8-way neighbors + CheckNeighbors(a_ChunkX, a_ChunkY, a_ChunkZ); + for (int i = 0; i < ARRAYCOUNT(g_NeighborCoords); i++) + { + CheckNeighbors(a_ChunkX + g_NeighborCoords[i].m_X, a_ChunkY, a_ChunkZ + g_NeighborCoords[i].m_Z); + } // for i - g_NeighborCoords[] +} + + + + + +void cWorldGenerator::CheckNeighbors(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +{ + if (!m_World->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ)) + { + return; + } + + // Check all 8-way neighbors, if they are all valid, generate foliage in this chunk: + int NumNeighbors = 0; + for (int i = 0; i < ARRAYCOUNT(g_NeighborCoords); i++) + { + if (m_World->IsChunkValid(a_ChunkX + g_NeighborCoords[i].m_X, a_ChunkY, a_ChunkZ + g_NeighborCoords[i].m_Z)) + { + NumNeighbors++; + } + } // for i - g_NeighborCoords[] + if (NumNeighbors == 8) + { + GenerateFoliage(a_ChunkX, a_ChunkY, a_ChunkZ); + } +} + + + + + static float GetNoise( float x, float y, cNoise & a_Noise ) { float oct1 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq1, y*cGenSettings::HeightFreq1 )*cGenSettings::HeightAmp1; @@ -187,7 +248,8 @@ void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, { a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIRT; } - } + } // for y + if (Top + 1 >= WATER_LEVEL + SAND_LEVEL) { // Replace top dirt with grass: @@ -201,111 +263,84 @@ void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER; } } - } - } + + // Generate small foliage (1-block): + int index = MakeIndex(x, Top - 1, z); + int TopY = Top - 1; + float val1 = Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f ); + float val2 = Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f ); + if( a_BlockData[index] == E_BLOCK_SAND ) + { + if ((val1 + val2 > 0.f) && ((r1.randInt() % 128) > 124)) + { + a_BlockData[ MakeIndex(x, TopY + 1, z) ] = E_BLOCK_CACTUS; + if ((r1.randInt() & 3) == 3) + { + a_BlockData[ MakeIndex(x, TopY + 2, z) ] = E_BLOCK_CACTUS; + } + continue; + } + } + else if( a_BlockData[index] == E_BLOCK_GRASS ) + { + float val3 = Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10 ); + float val4 = Noise.CubicNoise2D(xx * 0.05f + 20, zz * 0.05f + 20 ); + if( val3 > 0.2f && (r1.randInt()%128) > 124 ) + { + a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER; + } + else if( val4 > 0.2f && (r1.randInt()%128) > 124 ) + { + a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE; + } + else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 ) + { + a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM; + } + else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 ) + { + a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM; + } + } + } // for x + } // for z } -void cWorldGenerator::GenerateFoliage( cChunkPtr & a_Chunk ) +void cWorldGenerator::GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ) { - const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS; - const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT; - const ENUM_BLOCK_ID SandID = E_BLOCK_SAND; - const ENUM_BLOCK_ID SandStoneID = E_BLOCK_SANDSTONE; - const ENUM_BLOCK_ID CaveID = E_BLOCK_AIR; - - int PosX = a_Chunk->GetPosX(); - int PosZ = a_Chunk->GetPosZ(); - - cWorld* World = a_Chunk->GetWorld(); - cNoise m_Noise( World->GetWorldSeed() ); - char* BlockType = a_Chunk->pGetType(); - - for(int z = 0; z < 16; z++) for(int x = 0; x < 16; x++) + char BlockType[cChunk::c_NumBlocks]; + + if (!m_World->GetChunkBlocks(a_ChunkX, a_ChunkY, a_ChunkZ, BlockType)) { - // Find top most Y - int TopY = -1; - for(int y = 127; y > 0; y--) - { - int index = MakeIndex( x, y, z ); - if( BlockType[index] != E_BLOCK_AIR ) - { - TopY = y; - break; - } - } - if( TopY > 0 ) + LOGWARNING("Cannot generate foliage on chunk [%d, %d]", a_ChunkX, a_ChunkZ); + return; + } + + cNoise Noise(m_World->GetWorldSeed()); + for (int z = 0; z < 16; z++) + { + int zz = z + a_ChunkZ * 16; + for (int x = 0; x < 16; x++) { - // Change top dirt into grass and prevent sand from floating over caves - int index = MakeIndex( x, TopY, z ); - int index1 = MakeIndex( x, TopY-1, z ); - int index2 = MakeIndex( x, TopY-2, z ); - int index3 = MakeIndex( x, TopY-3, z ); - int index4 = MakeIndex( x, TopY-4, z ); - int index5 = MakeIndex( x, TopY-5, z ); - - if( BlockType[index] == SandID ) { - - if( BlockType[index1] == CaveID ) { - BlockType[ index ] = (char)SandStoneID; - } else if( BlockType[index2] == CaveID ) { - BlockType[ index1 ] = (char)SandStoneID; - } else if( BlockType[index3] == CaveID ) { - BlockType[ index2 ] = (char)SandStoneID; - } else if( BlockType[index4] == CaveID ) { - BlockType[ index3 ] = (char)SandStoneID; - } else if( BlockType[index5] == CaveID ) { - BlockType[ index4 ] = (char)SandStoneID; - } - - } - - if( BlockType[index] == DirtID ) - { - BlockType[ index ] = (char)GrassID; - } + int xx = x + a_ChunkX * 16; - // Plant sum trees + int TopY = m_World->GetHeight(xx, zz); + int index = MakeIndex(x, TopY - 1, z); + if (BlockType[index] == E_BLOCK_GRASS ) { - int xx = x + PosX*16; - int zz = z + PosZ*16; - - float val1 = m_Noise.CubicNoise2D( xx*0.1f, zz*0.1f ); - float val2 = m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f ); - if( BlockType[index] == SandID ) - { - if( (val1 + val2 > 0.f) && (r1.randInt()%128) > 124 && BlockType[index] == E_BLOCK_SAND ) - { - BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS; - if( (r1.randInt() & 3) == 3 ) - { - BlockType[ MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS; - } - continue; - } - } - else if( BlockType[index] == GrassID ) + float val1 = Noise.CubicNoise2D( xx * 0.1f, zz * 0.1f ); + float val2 = Noise.CubicNoise2D( xx * 0.01f, zz * 0.01f ); + if ((val1 + val2 > 0.2f) && ((r1.randInt() % 128) > 124)) { - float val3 = m_Noise.CubicNoise2D( xx*0.01f+10, zz*0.01f+10 ); - float val4 = m_Noise.CubicNoise2D( xx*0.05f+20, zz*0.05f+20 ); - if( val1 + val2 > 0.2f && (r1.randInt()%128) > 124 ) - World->GrowTree( xx, TopY, zz ); - else if( val3 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER; - else if( val4 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE; - else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM; - else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM; + m_World->GrowTree( xx, TopY, zz ); } - } - - } - } + } // if (Grass) + } // for x + } // for z } -- cgit v1.2.3