2012-01-29 14:28:19 -05:00
|
|
|
|
|
|
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
|
|
|
|
2011-12-25 21:39:43 -05:00
|
|
|
#include "cWorldGenerator.h"
|
|
|
|
#include "cNoise.h"
|
|
|
|
#include "cWorld.h"
|
|
|
|
#include "cChunk.h"
|
|
|
|
#include "cGenSettings.h"
|
|
|
|
|
|
|
|
#include "BlockID.h"
|
|
|
|
#include "Vector3i.h"
|
|
|
|
|
2012-01-29 14:28:19 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-02-16 12:45:26 -05:00
|
|
|
cWorldGenerator::cWorldGenerator(cWorld * a_World) :
|
|
|
|
m_World(a_World)
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-25 21:39:43 -05:00
|
|
|
cWorldGenerator::~cWorldGenerator()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2012-02-18 12:53:22 -05:00
|
|
|
void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
GenerateTerrain(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData);
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-25 21:39:43 -05:00
|
|
|
static float GetNoise( float x, float y, cNoise & a_Noise )
|
|
|
|
{
|
|
|
|
float oct1 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq1, y*cGenSettings::HeightFreq1 )*cGenSettings::HeightAmp1;
|
|
|
|
float oct2 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq2, y*cGenSettings::HeightFreq2 )*cGenSettings::HeightAmp2;
|
|
|
|
float oct3 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq3, y*cGenSettings::HeightFreq3 )*cGenSettings::HeightAmp3;
|
|
|
|
|
|
|
|
float height = a_Noise.CubicNoise2D( x*0.1f, y*0.1f )*2;
|
|
|
|
|
|
|
|
float flatness = ((a_Noise.CubicNoise2D( x*0.5f, y*0.5f ) + 1.f ) * 0.5f) * 1.1f; // 0 ... 1.5
|
|
|
|
flatness *= flatness * flatness;
|
|
|
|
|
|
|
|
return (oct1 + oct2 + oct3) * flatness + height;
|
|
|
|
}
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-25 21:39:43 -05:00
|
|
|
#define PI_2 (1.57079633f)
|
|
|
|
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;
|
|
|
|
|
|
|
|
return oct1;
|
|
|
|
}
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-25 21:39:43 -05:00
|
|
|
static float GetOreNoise( float x, float y, float z, cNoise & a_Noise )
|
|
|
|
{
|
|
|
|
float oct1 = a_Noise.CubicNoise3D( x*0.1f, y*0.1f, z*0.1f );
|
|
|
|
float oct2 = a_Noise.CubicNoise3D( x*0.05f, y*0.5f, z*0.05f );
|
|
|
|
|
|
|
|
oct2 *= oct2;
|
|
|
|
oct1 = (1 - (oct1 * oct1 *100)) * oct2;
|
|
|
|
//if( oct1 < 0.5f ) oct1 = 0;
|
|
|
|
//else oct1 = 1.f;
|
|
|
|
|
|
|
|
return oct1;
|
|
|
|
}
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-02-18 12:53:22 -05:00
|
|
|
unsigned int cWorldGenerator::MakeIndex(int x, int y, int z )
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
assert((x < 16) && (x > -1) && (y < 128) && (y > -1) && (z < 16) && (z > -1));
|
2011-12-25 21:39:43 -05:00
|
|
|
|
2012-02-18 12:53:22 -05:00
|
|
|
return y + (z * 128) + (x * 128 * 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData)
|
|
|
|
{
|
|
|
|
const int WATER_LEVEL = 60;
|
|
|
|
const int SAND_LEVEL = 3;
|
|
|
|
|
|
|
|
memset(a_BlockData, E_BLOCK_AIR, cChunk::c_BlockDataSize);
|
|
|
|
|
|
|
|
cNoise Noise(m_World->GetWorldSeed());
|
|
|
|
|
|
|
|
for (int z = 0; z < 16; z++)
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
const float zz = (float)(a_ChunkZ * 16 + z);
|
|
|
|
for (int x = 0; x < 16; x++)
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
|
|
|
// Place bedrock on bottom layer
|
2012-02-18 12:53:22 -05:00
|
|
|
a_BlockData[MakeIndex(x, 0, z)] = E_BLOCK_BEDROCK;
|
2011-12-25 21:39:43 -05:00
|
|
|
|
2012-02-18 12:53:22 -05:00
|
|
|
const float xx = (float)(a_ChunkX * 16 + x);
|
2011-12-25 21:39:43 -05:00
|
|
|
|
2012-02-18 12:53:22 -05:00
|
|
|
int Height = (int)(GetNoise( xx * 0.05f, zz * 0.05f, Noise ) * 16);
|
2011-12-25 21:39:43 -05:00
|
|
|
const int Lower = 64;
|
2012-02-18 12:53:22 -05:00
|
|
|
if ( Height + Lower > 127 )
|
|
|
|
{
|
|
|
|
Height = 127 - Lower;
|
|
|
|
}
|
|
|
|
const int Top = Lower + Height;
|
|
|
|
const float WaveNoise = 1; // m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f ) + 0.5f;
|
2011-12-25 21:39:43 -05:00
|
|
|
for( int y = 1; y < Top; ++y )
|
|
|
|
{
|
|
|
|
const float yy = (float)y;
|
|
|
|
// V prevent caves from getting too close to the surface
|
|
|
|
if( (Top - y > (WaveNoise*2) ) && cosf(GetMarbleNoise( xx, yy*0.5f, zz, Noise )) * fabs( cosf( yy*0.2f + WaveNoise*2 )*0.75f + WaveNoise ) > 0.5f )
|
|
|
|
{
|
|
|
|
if( y > 4 )
|
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_AIR;
|
|
|
|
if( z > 0 ) a_BlockData[ MakeIndex(x, y, z-1) ] = E_BLOCK_AIR;
|
|
|
|
if( z < 15 ) a_BlockData[ MakeIndex(x, y, z+1) ] = E_BLOCK_AIR;
|
|
|
|
if( x > 0 ) a_BlockData[ MakeIndex(x-1, y, z) ] = E_BLOCK_AIR;
|
|
|
|
if( x < 15 ) a_BlockData[ MakeIndex(x+1, y, z) ] = E_BLOCK_AIR;
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_LAVA;
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
}
|
2012-02-18 12:53:22 -05:00
|
|
|
else if ((y < 61) && (Top - y < SAND_LEVEL ))
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SAND;
|
|
|
|
}
|
|
|
|
else if ((y < 61) && (Top - y < 4 ))
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SANDSTONE;
|
|
|
|
}
|
|
|
|
else if (Top - y > ((WaveNoise + 1.5f) * 1.5f)) // rock and ores between 1.5 .. 4.5 deep
|
|
|
|
{
|
|
|
|
if ( GetOreNoise( xx, yy, zz, Noise ) > 0.5f )
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_COAL_ORE;
|
|
|
|
}
|
|
|
|
else if ( GetOreNoise( xx, yy+100.f, zz, Noise ) > 0.6f )
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_IRON_ORE;
|
|
|
|
}
|
|
|
|
else if (( yy < 20) && (GetOreNoise( xx * 1.5f, yy + 300.f, zz * 1.5f, Noise ) > 0.6f ))
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_REDSTONE_ORE;
|
|
|
|
}
|
|
|
|
else if (( yy < 30) && (GetOreNoise( xx * 2, yy + 200.f, zz * 2, Noise ) > 0.75f ))
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIAMOND_ORE;
|
|
|
|
}
|
|
|
|
else if (( yy < 40) && (GetOreNoise( xx * 2, yy + 100.f, zz * 2, Noise ) > 0.75f ))
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_GOLD_ORE;
|
|
|
|
}
|
2011-12-25 21:39:43 -05:00
|
|
|
else
|
2012-02-18 12:53:22 -05:00
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STONE;
|
|
|
|
}
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
else
|
2012-02-18 12:53:22 -05:00
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIRT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Top + 1 >= WATER_LEVEL + SAND_LEVEL)
|
|
|
|
{
|
|
|
|
// Replace top dirt with grass:
|
|
|
|
a_BlockData[MakeIndex(x, Top - 1, z)] = E_BLOCK_GRASS;
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
2012-02-18 12:53:22 -05:00
|
|
|
else
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
// Add water up to the WATER_LEVEL:
|
|
|
|
for (int y = Top; y < WATER_LEVEL; ++y )
|
|
|
|
{
|
|
|
|
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER;
|
|
|
|
}
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
2012-02-18 12:53:22 -05:00
|
|
|
void cWorldGenerator::GenerateFoliage( cChunkPtr & a_Chunk )
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
|
|
|
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++)
|
|
|
|
{
|
|
|
|
// Find top most Y
|
|
|
|
int TopY = -1;
|
|
|
|
for(int y = 127; y > 0; y--)
|
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
int index = MakeIndex( x, y, z );
|
2011-12-25 21:39:43 -05:00
|
|
|
if( BlockType[index] != E_BLOCK_AIR )
|
|
|
|
{
|
|
|
|
TopY = y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( TopY > 0 )
|
|
|
|
{
|
|
|
|
// Change top dirt into grass and prevent sand from floating over caves
|
2012-02-18 12:53:22 -05:00
|
|
|
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 );
|
2011-12-25 21:39:43 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Plant sum trees
|
|
|
|
{
|
|
|
|
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 )
|
|
|
|
{
|
2011-12-26 04:09:47 -05:00
|
|
|
if( (val1 + val2 > 0.f) && (r1.randInt()%128) > 124 && BlockType[index] == E_BLOCK_SAND )
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS;
|
2011-12-26 04:09:47 -05:00
|
|
|
if( (r1.randInt() & 3) == 3 )
|
2011-12-25 21:39:43 -05:00
|
|
|
{
|
2012-02-18 12:53:22 -05:00
|
|
|
BlockType[ MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS;
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( BlockType[index] == GrassID )
|
|
|
|
{
|
|
|
|
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 );
|
2011-12-26 04:09:47 -05:00
|
|
|
if( val1 + val2 > 0.2f && (r1.randInt()%128) > 124 )
|
2011-12-25 21:39:43 -05:00
|
|
|
World->GrowTree( xx, TopY, zz );
|
2011-12-26 04:09:47 -05:00
|
|
|
else if( val3 > 0.2f && (r1.randInt()%128) > 124 )
|
2012-02-18 12:53:22 -05:00
|
|
|
BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER;
|
2011-12-26 04:09:47 -05:00
|
|
|
else if( val4 > 0.2f && (r1.randInt()%128) > 124 )
|
2012-02-18 12:53:22 -05:00
|
|
|
BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE;
|
2011-12-26 04:09:47 -05:00
|
|
|
else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
|
2012-02-18 12:53:22 -05:00
|
|
|
BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM;
|
2011-12-26 04:09:47 -05:00
|
|
|
else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
|
2012-02-18 12:53:22 -05:00
|
|
|
BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM;
|
2011-12-25 21:39:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-13 16:47:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|