#include "DimensionGenerator.h" #include "Constants.h" #include "Noise.h" #include "NoBlock.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( BiomGenerator* gen : biomGenerators ) { double noise = zNoise->getNoise( x * gen->getBiomXMultiplier(), y * gen->getBiomYMultiplier(), z ) * gen->getBiomOutputMultiplier(); if( noise > firstChoiceWeight ) { secondChoiceWeight = firstChoiceWeight; *secondChoice = *firstChoice; firstChoiceWeight = noise; *firstChoice = gen; } else if( noise > secondChoiceWeight ) { secondChoiceWeight = noise; *secondChoice = gen; } z++; } } void DimensionGenerator::registerBiom( BiomGenerator* generator ) { biomGenerators.add( generator ); } Chunk* DimensionGenerator::generateChunk( Noise* zNoise, Game* zGame, int centerX, int centerY ) { 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++ ) { for( int z = 0; z < WORLD_HEIGHT; z++ ) { auto generated = generateBlock( zNoise, zGame, { x + centerX, y + centerY, z } ); if( generated.isA() ) chunk->putBlockAt( Framework::Vec3( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), generated ); else chunk->putBlockTypeAt( Framework::Vec3( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), generated ); } } } return chunk; } Framework::Either DimensionGenerator::generateBlock( Noise* zNoise, Game* zGame, Framework::Vec3 location ) { BiomGenerator* actualBiom; BiomGenerator* neighborBiom; double actualWeight; double neighborWeight; findBiom( location.x, location.y, zNoise, &actualBiom, &neighborBiom, actualWeight, neighborWeight ); double actualHeight = zNoise->getNoise( location.x * actualBiom->getAirLevelXMultiplier(), location.y * actualBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * actualBiom->getAirLevelOutputMultiplier(); double neighborHeight = zNoise->getNoise( location.x * neighborBiom->getAirLevelXMultiplier(), location.y * 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)); if( location.z < height ) { auto actualBlock = actualBiom->getBlock( zNoise, location.x, location.y, location.z, zGame ); auto neighborBlock = neighborBiom->getBlock( zNoise, location.x, location.y, location.z, zGame ); return interpolator->interpolateBlocks( actualBlock, neighborBlock, actualHeight, neighborWeight, zNoise ); } return AirBlockBlockType::ID; } int DimensionGenerator::getDimensionId() const { return dimensionId; }