#include "DimensionGenerator.h" #include "Constants.h" #include "Noise.h" DimensionGenerator::DimensionGenerator( BiomInterpolator *interpolator, int dimensionId ) : ReferenceCounter(), interpolator( interpolator ), dimensionId( dimensionId ) { StaticRegistry::INSTANCE.registerT( this, dimensionId ); } DimensionGenerator::~DimensionGenerator() { interpolator->release(); } void DimensionGenerator::findBiom( int x, int y, Noise *zNoise, BiomGenerator **firstChoice, BiomGenerator **secondChoice, double &firstChoiceWeight, double &secondChoiceWeight ) { *firstChoice = biomGenerators.z( 0 ); *secondChoice = biomGenerators.z( 0 ); firstChoiceWeight = 0; secondChoiceWeight = 0; int z = BIOM_GENERATION_Z_OFFSET; for( Framework::Iterator it = biomGenerators.getIterator(); it; it++ ) { double noise = zNoise->getNoise( x * it->getBiomXMultiplier(), y * it->getBiomYMultiplier(), z ) * it->getBiomOutputMultiplier(); if( noise > firstChoiceWeight ) { secondChoiceWeight = firstChoiceWeight; *secondChoice = *firstChoice; firstChoiceWeight = noise; *firstChoice = it; } else if( noise > secondChoiceWeight ) { secondChoiceWeight = noise; *secondChoice = it; } z++; } } void DimensionGenerator::registerBiom( BiomGenerator *generator ) { biomGenerators.add( generator ); } Chunk *DimensionGenerator::generateChunk( Noise *zNoise, Game *zGame, int centerX, int centerY ) { BiomGenerator *actualBiom; BiomGenerator *neighborBiom; double actualWeight; double neighborWeight; Chunk *chunk = new Chunk( Framework::Punkt( centerX, centerY ), zGame, dimensionId ); for( int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++ ) { for( int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++ ) { findBiom( x + centerX, y + centerY, zNoise, &actualBiom, &neighborBiom, actualWeight, neighborWeight ); double actualHeight = zNoise->getNoise( ( x + centerX ) * actualBiom->getAirLevelXMultiplier(), ( y + centerY ) * actualBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * actualBiom->getAirLevelOutputMultiplier(); double neighborHeight = zNoise->getNoise( ( x + centerX ) * neighborBiom->getAirLevelXMultiplier(), ( y + centerY ) * neighborBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * neighborBiom->getAirLevelOutputMultiplier(); int height = MIN_AIR_LEVEL; if( actualWeight + neighborWeight > 0 ) height += (int)( ( ( actualHeight * actualHeight + neighborHeight * neighborWeight ) / ( actualWeight + neighborWeight ) ) * ( MAX_AIR_LEVEL - MIN_AIR_LEVEL ) ); for( int z = 0; z < WORLD_HEIGHT; z++ ) { if( z < height ) { Block *actualBlock = actualBiom->getBlock( zNoise, x + centerX, y + centerY, z, zGame ); Block *neighborBlock = neighborBiom->getBlock( zNoise, x + centerX, y + centerY, z, zGame ); chunk->putBlockAt( Framework::Vec3( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), interpolator->interpolateBlocks( actualBlock, neighborBlock, actualHeight, neighborWeight, zNoise ) ); } } } } return chunk; } int DimensionGenerator::getDimensionId() const { return dimensionId; }