|
@@ -8,7 +8,9 @@
|
|
|
|
|
|
DimensionGenerator::DimensionGenerator( int dimensionId )
|
|
|
: ReferenceCounter(),
|
|
|
- dimensionId( dimensionId )
|
|
|
+ dimensionId( dimensionId ),
|
|
|
+ minTemplateAffectedPosition( 0, 0, 0 ),
|
|
|
+ maxTemplateAffectedPosition( 0, 0, 0 )
|
|
|
{
|
|
|
StaticRegistry<DimensionGenerator>::INSTANCE.registerT( this, dimensionId );
|
|
|
}
|
|
@@ -35,10 +37,64 @@ void DimensionGenerator::registerBiom( BiomGenerator* generator, double possibil
|
|
|
{
|
|
|
biomGenerators.add( generator );
|
|
|
biomDistribution.add( possibility );
|
|
|
+ for( auto t : generator->getTemplates() )
|
|
|
+ {
|
|
|
+ minTemplateAffectedPosition.x = MIN( minTemplateAffectedPosition.x, t->getMinAffectedOffset().x );
|
|
|
+ minTemplateAffectedPosition.y = MIN( minTemplateAffectedPosition.y, t->getMinAffectedOffset().y );
|
|
|
+ minTemplateAffectedPosition.z = MIN( minTemplateAffectedPosition.z, t->getMinAffectedOffset().z );
|
|
|
+ maxTemplateAffectedPosition.x = MAX( maxTemplateAffectedPosition.x, t->getMaxAffectedOffset().x );
|
|
|
+ maxTemplateAffectedPosition.y = MAX( maxTemplateAffectedPosition.y, t->getMaxAffectedOffset().y );
|
|
|
+ maxTemplateAffectedPosition.z = MAX( maxTemplateAffectedPosition.z, t->getMaxAffectedOffset().z );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Framework::RCArray<GeneratedStructure>* DimensionGenerator::getGeneratedStructoresForArea( int seed, Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos )
|
|
|
+{
|
|
|
+ Framework::RCArray<GeneratedStructure>* result = new Framework::RCArray<GeneratedStructure>();
|
|
|
+
|
|
|
+ int minSearchX = minPos.x - maxTemplateAffectedPosition.x;
|
|
|
+ int minSearchY = minPos.y - maxTemplateAffectedPosition.y;
|
|
|
+ int minSearchZ = MAX( minPos.z - maxTemplateAffectedPosition.z, 0 );
|
|
|
+ int maxSearchX = maxPos.x - minTemplateAffectedPosition.x;
|
|
|
+ int maxSearchY = maxPos.y - minTemplateAffectedPosition.y;
|
|
|
+ int maxSearchZ = MIN( maxPos.z - minTemplateAffectedPosition.z, WORLD_HEIGHT - 1 );
|
|
|
+
|
|
|
+ Noise* structureNoise = zStructureNoise( seed + dimensionId );
|
|
|
+ for( int x = minSearchX; x <= maxSearchX; x++ )
|
|
|
+ {
|
|
|
+ for( int y = minSearchY; y <= maxSearchY; y++ )
|
|
|
+ {
|
|
|
+ BiomGenerator* biom = zBiomGenerator( seed + dimensionId, x, y );
|
|
|
+ int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise( seed + dimensionId )->getNoise( (double)(x), (double)(y), 0.0 ) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
|
|
|
+ for( int z = minSearchZ; z <= maxSearchZ; z++ )
|
|
|
+ {
|
|
|
+ if( z < height )
|
|
|
+ {
|
|
|
+ double rValue = structureNoise->getNoise( (double)x, (double)y, (double)z );
|
|
|
+ double probSum = 0;
|
|
|
+ for( auto t : biom->getTemplates() )
|
|
|
+ {
|
|
|
+ if( t->isGenerationPossable( Framework::Vec3<int>( x, y, z ), height - z ) )
|
|
|
+ {
|
|
|
+ if( rValue - probSum <= t->getPropability() )
|
|
|
+ {
|
|
|
+ result->add( t->generateAt( Framework::Vec3<int>( x, y, z ), structureNoise ) );
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ probSum += t->getPropability();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
Chunk* DimensionGenerator::generateChunk( int seed, int centerX, int centerY )
|
|
|
{
|
|
|
+ Framework::RCArray<GeneratedStructure>* structures = getGeneratedStructoresForArea( seed, Framework::Vec3<int>( centerX - CHUNK_SIZE / 2, centerY - CHUNK_SIZE / 2, 0 ), Framework::Vec3<int>( centerX + CHUNK_SIZE / 2, centerY + CHUNK_SIZE / 2, WORLD_HEIGHT - 1 ) );
|
|
|
std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
|
|
|
Chunk* chunk = new Chunk( Framework::Punkt( centerX, centerY ), dimensionId );
|
|
|
for( int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++ )
|
|
@@ -48,11 +104,28 @@ Chunk* DimensionGenerator::generateChunk( int seed, int centerX, int centerY )
|
|
|
BiomGenerator* biom = zBiomGenerator( seed + dimensionId, x + centerX, y + centerY );
|
|
|
// TODO: use Noise interpolator for height map between different bioms
|
|
|
int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise( seed + dimensionId )->getNoise( (double)(x + centerX), (double)(y + centerY), 0.0 ) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
|
|
|
+ int maxSurfaceHeight = (1 - (height - MIN_AIR_LEVEL) / (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
|
|
|
+ int actualSurfaceHeight = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART) + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART * (float)biom->zHeightMapNoise( seed + dimensionId )->getNoise( (double)(x + centerX), (double)(y + centerY), 10.0 )));
|
|
|
for( int z = 0; z < WORLD_HEIGHT; z++ )
|
|
|
{
|
|
|
Framework::Either<Block*, int> generated = AirBlockBlockType::ID;
|
|
|
- if( z < height )
|
|
|
- generated = biom->getBlock( x + centerX, y + centerY, z );
|
|
|
+ bool structureAffected = 0;
|
|
|
+ for( auto structure : *structures )
|
|
|
+ {
|
|
|
+ if( structure->isBlockAffected( Framework::Vec3<int>( x + centerX, y + centerY, z ) ) )
|
|
|
+ {
|
|
|
+ generated = structure->generateBlockAt( Framework::Vec3<int>( x + centerX, y + centerY, z ) );
|
|
|
+ structureAffected = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( !structureAffected )
|
|
|
+ {
|
|
|
+ if( z < height && z >= height - actualSurfaceHeight )
|
|
|
+ generated = biom->generateSurfaceBlock( x + centerX, y + centerY, z );
|
|
|
+ else if( z < height )
|
|
|
+ generated = biom->generateBelowSurfaceBlock( x + centerX, y + centerY, z );
|
|
|
+ }
|
|
|
if( generated.isA() )
|
|
|
chunk->putBlockAt( Framework::Vec3<int>( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), generated );
|
|
|
else
|
|
@@ -60,16 +133,32 @@ Chunk* DimensionGenerator::generateChunk( int seed, int centerX, int centerY )
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ structures->release();
|
|
|
return chunk;
|
|
|
}
|
|
|
|
|
|
Framework::Either<Block*, int> DimensionGenerator::generateBlock( int seed, Framework::Vec3<int> location )
|
|
|
{
|
|
|
+ Framework::RCArray<GeneratedStructure>* structures = getGeneratedStructoresForArea( seed, location, location );
|
|
|
BiomGenerator* biom = zBiomGenerator( seed + dimensionId, location.x, location.y );
|
|
|
// TODO: use Noise interpolator for height map between different bioms
|
|
|
int height = MIN_AIR_LEVEL + (int)(biom->zHeightMapNoise( seed + dimensionId )->getNoise( (double)(location.x), (double)(location.y), 0.0 ) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
|
|
|
- if( location.z < height )
|
|
|
- return biom->getBlock( location.x, location.y, location.z );
|
|
|
+ int maxSurfaceHeight = (1 - (height - MIN_AIR_LEVEL) / (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
|
|
|
+ int actualSurfaceHeight = (int)((float)maxSurfaceHeight * (1.f - VARIABLE_SURFACE_PART) + ((float)maxSurfaceHeight * VARIABLE_SURFACE_PART * (float)biom->zHeightMapNoise( seed + dimensionId )->getNoise( (double)(location.x), (double)(location.y), 10.0 )));
|
|
|
+ for( auto structure : *structures )
|
|
|
+ {
|
|
|
+ if( structure->isBlockAffected( location ) )
|
|
|
+ {
|
|
|
+ auto generated = structure->generateBlockAt( location );
|
|
|
+ structures->release();
|
|
|
+ return generated;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ structures->release();
|
|
|
+ if( location.z < height && location.z >= height - actualSurfaceHeight )
|
|
|
+ return biom->generateSurfaceBlock( location.x, location.y, location.z );
|
|
|
+ else if( location.z < height )
|
|
|
+ return biom->generateBelowSurfaceBlock( location.x, location.y, location.z );
|
|
|
return AirBlockBlockType::ID;
|
|
|
}
|
|
|
|