DimensionGenerator.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "DimensionGenerator.h"
  2. #include "Constants.h"
  3. #include "Noise.h"
  4. #include "NoBlock.h"
  5. #include <iostream>
  6. DimensionGenerator::DimensionGenerator( BiomInterpolator* interpolator, int dimensionId )
  7. : ReferenceCounter(),
  8. interpolator( interpolator ),
  9. dimensionId( dimensionId )
  10. {
  11. StaticRegistry<DimensionGenerator>::INSTANCE.registerT( this, dimensionId );
  12. }
  13. DimensionGenerator::~DimensionGenerator()
  14. {
  15. interpolator->release();
  16. }
  17. void DimensionGenerator::findBiom( int x, int y, Noise* zNoise, BiomGenerator** firstChoice, BiomGenerator** secondChoice, double& firstChoiceWeight, double& secondChoiceWeight )
  18. {
  19. *firstChoice = biomGenerators.z( 0 );
  20. *secondChoice = biomGenerators.z( 0 );
  21. firstChoiceWeight = 0;
  22. secondChoiceWeight = 0;
  23. int z = BIOM_GENERATION_Z_OFFSET;
  24. for( BiomGenerator* gen : biomGenerators )
  25. {
  26. double noise = zNoise->getNoise( x * gen->getBiomXMultiplier(), y * gen->getBiomYMultiplier(), z ) * gen->getBiomOutputMultiplier();
  27. if( noise > firstChoiceWeight )
  28. {
  29. secondChoiceWeight = firstChoiceWeight;
  30. *secondChoice = *firstChoice;
  31. firstChoiceWeight = noise;
  32. *firstChoice = gen;
  33. }
  34. else if( noise > secondChoiceWeight )
  35. {
  36. secondChoiceWeight = noise;
  37. *secondChoice = gen;
  38. }
  39. z++;
  40. }
  41. }
  42. void DimensionGenerator::registerBiom( BiomGenerator* generator )
  43. {
  44. biomGenerators.add( generator );
  45. }
  46. Chunk* DimensionGenerator::generateChunk( Noise* zNoise, Game* zGame, int centerX, int centerY )
  47. {
  48. std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
  49. Chunk* chunk = new Chunk( Framework::Punkt( centerX, centerY ), zGame, dimensionId );
  50. for( int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++ )
  51. {
  52. for( int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++ )
  53. {
  54. BiomGenerator* actualBiom;
  55. BiomGenerator* neighborBiom;
  56. double actualWeight;
  57. double neighborWeight;
  58. findBiom( x + centerX, y + centerY, zNoise, &actualBiom, &neighborBiom, actualWeight, neighborWeight );
  59. double actualHeight = zNoise->getNoise( (x + centerX) * actualBiom->getAirLevelXMultiplier(), (y + centerY) * actualBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * actualBiom->getAirLevelOutputMultiplier() + actualBiom->getAirLevelOutputAddition();
  60. double neighborHeight = zNoise->getNoise( (x + centerX) * neighborBiom->getAirLevelXMultiplier(), (y + centerY) * neighborBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * neighborBiom->getAirLevelOutputMultiplier() + neighborBiom->getAirLevelOutputAddition();
  61. int height = MIN_AIR_LEVEL;
  62. if( actualWeight + neighborWeight > 0 )
  63. height += (int)(((actualHeight * actualWeight + neighborHeight * neighborWeight) / (actualWeight + neighborWeight)) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
  64. for( int z = 0; z < WORLD_HEIGHT; z++ )
  65. {
  66. Framework::Either<Block*, int> generated = AirBlockBlockType::ID;
  67. if( z < height )
  68. {
  69. auto actualBlock = actualBiom->getBlock( zNoise, x + centerX, y + centerY, z, zGame );
  70. auto neighborBlock = neighborBiom->getBlock( zNoise, x + centerX, y + centerY, z, zGame );
  71. generated = interpolator->interpolateBlocks( actualBlock, neighborBlock, actualHeight, neighborWeight, zNoise );
  72. }
  73. if( generated.isA() )
  74. chunk->putBlockAt( Framework::Vec3<int>( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), generated );
  75. else
  76. chunk->putBlockTypeAt( Framework::Vec3<int>( x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z ), generated );
  77. }
  78. }
  79. }
  80. return chunk;
  81. }
  82. Framework::Either<Block*, int> DimensionGenerator::generateBlock( Noise* zNoise, Game* zGame, Framework::Vec3<int> location )
  83. {
  84. BiomGenerator* actualBiom;
  85. BiomGenerator* neighborBiom;
  86. double actualWeight;
  87. double neighborWeight;
  88. findBiom( location.x, location.y, zNoise, &actualBiom, &neighborBiom, actualWeight, neighborWeight );
  89. double actualHeight = zNoise->getNoise( location.x * actualBiom->getAirLevelXMultiplier(), location.y * actualBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * actualBiom->getAirLevelOutputMultiplier() + actualBiom->getAirLevelOutputAddition();
  90. double neighborHeight = zNoise->getNoise( location.x * neighborBiom->getAirLevelXMultiplier(), location.y * neighborBiom->getAirLevelYMultiplier(), AIR_LEVEL_Z_OFFSET ) * neighborBiom->getAirLevelOutputMultiplier() + neighborBiom->getAirLevelOutputAddition();
  91. int height = MIN_AIR_LEVEL;
  92. if( actualWeight + neighborWeight > 0 )
  93. height += (int)(((actualHeight * actualWeight + neighborHeight * neighborWeight) / (actualWeight + neighborWeight)) * (MAX_AIR_LEVEL - MIN_AIR_LEVEL));
  94. if( location.z < height )
  95. {
  96. auto actualBlock = actualBiom->getBlock( zNoise, location.x, location.y, location.z, zGame );
  97. auto neighborBlock = neighborBiom->getBlock( zNoise, location.x, location.y, location.z, zGame );
  98. return interpolator->interpolateBlocks( actualBlock, neighborBlock, actualHeight, neighborWeight, zNoise );
  99. }
  100. return AirBlockBlockType::ID;
  101. }
  102. int DimensionGenerator::getDimensionId() const
  103. {
  104. return dimensionId;
  105. }