Try to add climate based biome scattering (commented now)

This commit is contained in:
NSDeathman 2026-03-12 22:18:07 +03:00
parent e0f2b2ca4b
commit ec93a8b85b
5 changed files with 37 additions and 97 deletions

View file

@ -9,7 +9,6 @@
#include "..\Minecraft.Client\Minecraft.h" #include "..\Minecraft.Client\Minecraft.h"
#include "..\Minecraft.Client\ProgressRenderer.h" #include "..\Minecraft.Client\ProgressRenderer.h"
// 4J - removal of separate temperature & downfall layers brought forward from 1.2.3
void BiomeSource::_init() void BiomeSource::_init()
{ {
layer = nullptr; layer = nullptr;
@ -17,7 +16,6 @@ void BiomeSource::_init()
cache = new BiomeCache(this); cache = new BiomeCache(this);
// 4J-PB - Moving forward plains as a spawnable biome (mainly for the Superflat world)
playerSpawnBiomes.push_back(Biome::plains); playerSpawnBiomes.push_back(Biome::plains);
playerSpawnBiomes.push_back(Biome::forest); playerSpawnBiomes.push_back(Biome::forest);
playerSpawnBiomes.push_back(Biome::forestHills); playerSpawnBiomes.push_back(Biome::forestHills);
@ -25,14 +23,23 @@ void BiomeSource::_init()
playerSpawnBiomes.push_back(Biome::taigaHills); playerSpawnBiomes.push_back(Biome::taigaHills);
playerSpawnBiomes.push_back(Biome::jungle); playerSpawnBiomes.push_back(Biome::jungle);
playerSpawnBiomes.push_back(Biome::jungleHills); playerSpawnBiomes.push_back(Biome::jungleHills);
playerSpawnBiomes.push_back(Biome::desert);
playerSpawnBiomes.push_back(Biome::extremeHills);
playerSpawnBiomes.push_back(Biome::swampland);
playerSpawnBiomes.push_back(Biome::iceFlats);
playerSpawnBiomes.push_back(Biome::iceMountains);
playerSpawnBiomes.push_back(Biome::mushroomIsland);
playerSpawnBiomes.push_back(Biome::mushroomIslandShore);
playerSpawnBiomes.push_back(Biome::beaches);
playerSpawnBiomes.push_back(Biome::desertHills);
playerSpawnBiomes.push_back(Biome::smallerExtremeHills);
} }
void BiomeSource::_init(int64_t seed, LevelType *generator) void BiomeSource::_init(int64_t seed, LevelType *generator)
{ {
_init(); _init();
// LayerArray layers = Layer::getDefaultLayers(seed, generator); LayerArray layers = Layer::getDefaultLayers(seed, generator);
LayerArray layers = getClimateLayers(seed, generator);
layer = layers[0]; layer = layers[0];
zoomedLayer = layers[1]; zoomedLayer = layers[1];
@ -149,16 +156,6 @@ void BiomeSource::getTemperatureBlock(floatArray& temperatures, int x, int z, in
} }
} }
LayerArray BiomeSource::getClimateLayers(int64_t seed, LevelType* generator)
{
LayerArray layers(2);
// Ãðóáûé ñëîé (ìàñøòàá 0.04) — äëÿ ïðåäâàðèòåëüíûõ ïðîâåðîê, åñëè íóæåí
layers[0] = std::make_shared<ClimateLayer>(seed, 4, 0.04);
// Äåòàëüíûé ñëîé (ìàñøòàá 0.01) — äëÿ ôèíàëüíîé êàðòû áèîìîâ
layers[1] = std::make_shared<ClimateLayer>(seed, 4, 0.01);
return layers;
}
BiomeArray BiomeSource::getRawBiomeBlock(int x, int z, int w, int h) const BiomeArray BiomeSource::getRawBiomeBlock(int x, int z, int w, int h) const
{ {
BiomeArray biomes; BiomeArray biomes;
@ -453,7 +450,7 @@ int64_t BiomeSource::findSeed(LevelType *generator)
// Raw biome data has one result per 4x4 group of tiles. // Raw biome data has one result per 4x4 group of tiles.
// Removing a border of 8 from each side since we'll be doing special things at the edge to turn our world into an island, and so don't want to count things // Removing a border of 8 from each side since we'll be doing special things at the edge to turn our world into an island, and so don't want to count things
// in the edge region in case they later get removed // in the edge region in case they later get removed
static const int biomeWidth = ( 54 * 4 ) - 16; // Should be even so we can offset evenly static const int biomeWidth = ( 64 * 2 ) - 16; // Should be even so we can offset evenly
static const int biomeOffset = -( biomeWidth / 2 ); static const int biomeOffset = -( biomeWidth / 2 );
// Storage for our biome indices // Storage for our biome indices
@ -468,7 +465,7 @@ int64_t BiomeSource::findSeed(LevelType *generator)
// Just keeping trying to generate seeds until we find one that matches our criteria // Just keeping trying to generate seeds until we find one that matches our criteria
do do
{ {
int64_t seed = pr->nextLong(); int64_t seed = System::currentTimeMillis() ^ (tryCount << 32) ^ (int64_t)pr->nextLong();
BiomeSource *biomeSource = new BiomeSource(seed,generator); BiomeSource *biomeSource = new BiomeSource(seed,generator);
biomeSource->getRawBiomeIndices(indices, biomeOffset, biomeOffset, biomeWidth, biomeWidth); biomeSource->getRawBiomeIndices(indices, biomeOffset, biomeOffset, biomeWidth, biomeWidth);
@ -575,82 +572,21 @@ void BiomeSource::getFracs(intArray indices, float *fracs)
// 4J added - determine if this particular set of fractional amounts of biome types matches are requirements // 4J added - determine if this particular set of fractional amounts of biome types matches are requirements
bool BiomeSource::getIsMatch(float *frac) bool BiomeSource::getIsMatch(float* frac)
{ {
// A true for a particular biome type here marks it as one that *has* to be present // Îêåàí ìîæåò çàíèìàòü äî 50%
static const bool critical[Biome::BIOME_COUNT] = { if (frac[0] > 0.5f) return false;
true, // ocean
true, // plains
true, // desert
false, // extreme hills
true, // forest
true, // taiga
true, // swamps
false, // river
false, // hell
false, // end biome
false, // frozen ocean
false, // frozen river
false, // ice flats
false, // ice mountains
true, // mushroom island / shore
false, // mushroom shore (combined with above)
false, // beach
false, // desert hills (combined with desert)
false, // forest hills (combined with forest)
false, // taiga hills (combined with taga)
false, // small extreme hills
true, // jungle
false, // jungle hills (combined with jungle)
};
// Îñíîâíûå áèîìû, êîòîðûå äîëæíû ïðèñóòñòâîâàòü
// Don't want more than 15% ocean //static const int required[] = { 1, 2, 4, 5 }; // plains, desert, forest, taiga
if( frac[0] > 0.15f ) //for (int i : required) {
{ // if (frac[i] < 0.01f) return false;
return false; //}
}
// Consider mushroom shore & islands as the same by finding max
frac[14] = ( ( frac[15] > frac[14] ) ? frac[15] : frac[14] );
// Merge desert and desert hills
frac[2] = ( ( frac[17] > frac[2] ) ? frac[17] : frac[2] );
// Merge forest and forest hills
frac[4] = ( ( frac[18] > frac[4] ) ? frac[18] : frac[4] );
// Merge taiga and taiga hills
frac[5] = ( ( frac[19] > frac[5] ) ? frac[19] : frac[5] );
// Merge jungle and jungle hills
frac[21] = ( ( frac[22] > frac[21] ) ? frac[22] : frac[21] );
// Loop through all biome types, and:
// (1) count them
// (2) give up if one of the critical ones is missing
int typeCount = 0; int typeCount = 0;
for( int i = 0; i < Biome::BIOME_COUNT; i++ ) for (int i = 0; i < Biome::BIOME_COUNT; i++) {
{ if (i == 15 || i == 17 || i == 18 || i == 19 || i == 22) continue;
// We want to skip some where we have merged with another type if (frac[i] > 0.001f) typeCount++;
if(i == 15 || i == 17 || i == 18 || i == 19 || i == 22) continue;
// Consider 0.1% as being "present" - this equates an area of about 3 chunks
if( frac[i] > 0.001f )
{
typeCount++;
} }
else return typeCount >= 6;
{
// If a critical biome is missing, just give up
if( critical[i] )
{
return false;
}
}
}
// Consider as suitable if we've got all the critical ones, and in total 9 or more - currently there's 8 critical so this just forces at least 1 more others
return ( typeCount >= 9 );
} }

View file

@ -47,8 +47,6 @@ public:
virtual Biome *getBiome(ChunkPos *cp); virtual Biome *getBiome(ChunkPos *cp);
virtual Biome *getBiome(int x, int z); virtual Biome *getBiome(int x, int z);
static LayerArray getClimateLayers(int64_t seed, LevelType* generator);
// 4J - changed the interface for these methods, mainly for thread safety // 4J - changed the interface for these methods, mainly for thread safety
virtual float getDownfall(int x, int z) const; virtual float getDownfall(int x, int z) const;
virtual floatArray getDownfallBlock(int x, int z, int w, int h) const; virtual floatArray getDownfallBlock(int x, int z, int w, int h) const;

View file

@ -4,9 +4,10 @@
#include "Mth.h" #include "Mth.h"
#include "IntCache.h" #include "IntCache.h"
ClimateLayer::ClimateLayer(int64_t seed, int octaves, double scale) ClimateLayer::ClimateLayer(int64_t seed, int octaves, double scale, shared_ptr<Layer> parent)
: Layer(seed), scale(scale) : Layer(seed), scale(scale)
{ {
this->parent = parent;
Random random(seed); Random random(seed);
temperatureNoise = new PerlinNoise(&random, octaves); temperatureNoise = new PerlinNoise(&random, octaves);
humidityNoise = new PerlinNoise(&random, octaves); humidityNoise = new PerlinNoise(&random, octaves);
@ -58,17 +59,22 @@ intArray ClimateLayer::getArea(int xo, int yo, int w, int h)
{ {
IntCache::releaseAll(); IntCache::releaseAll();
intArray result = IntCache::allocate(w * h); intArray result = IntCache::allocate(w * h);
intArray parentMap = parent->getArea(xo, yo, w, h); // ïîëó÷àåì êàðòó ñóøè/îêåàíà
for (int y = 0; y < h; ++y) { for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) { for (int x = 0; x < w; ++x) {
int parentVal = parentMap[x + y * w];
if (parentVal == 0) { // îêåàí
result[x + y * w] = 0;
continue;
}
int worldX = xo + x; int worldX = xo + x;
int worldY = yo + y; int worldY = yo + y;
// Получаем значения шума в диапазоне примерно [-1, 1]
double tempNoise = temperatureNoise->getValue(worldX * scale, worldY * scale); double tempNoise = temperatureNoise->getValue(worldX * scale, worldY * scale);
double humNoise = humidityNoise->getValue(worldX * scale, worldY * scale); double humNoise = humidityNoise->getValue(worldX * scale, worldY * scale);
// Нормализуем в [0, 1] (логистическая функция или просто clamp)
float normTemp = Mth::clamp((float)((tempNoise + 1.0) * 0.5), 0.0f, 1.0f); float normTemp = Mth::clamp((float)((tempNoise + 1.0) * 0.5), 0.0f, 1.0f);
float normHum = Mth::clamp((float)((humNoise + 1.0) * 0.5), 0.0f, 1.0f); float normHum = Mth::clamp((float)((humNoise + 1.0) * 0.5), 0.0f, 1.0f);
@ -76,6 +82,5 @@ intArray ClimateLayer::getArea(int xo, int yo, int w, int h)
result[x + y * w] = biome->id; result[x + y * w] = biome->id;
} }
} }
return result; return result;
} }

View file

@ -22,7 +22,7 @@ private:
Biome* getBiomeForClimate(float temp, float hum) const; Biome* getBiomeForClimate(float temp, float hum) const;
public: public:
ClimateLayer(int64_t seed, int octaves = 4, double scale = 0.01); ClimateLayer(int64_t seed, int octaves, double scale, shared_ptr<Layer> parent);
virtual ~ClimateLayer(); virtual ~ClimateLayer();
virtual intArray getArea(int xo, int yo, int w, int h) override; virtual intArray getArea(int xo, int yo, int w, int h) override;

View file

@ -22,6 +22,7 @@
#include "VoronoiZoom.h" #include "VoronoiZoom.h"
#include "ZoomLayer.h" #include "ZoomLayer.h"
#include "GrowMushroomIslandLayer.h" // 4J added #include "GrowMushroomIslandLayer.h" // 4J added
#include "ClimateLayer.h"
// 1.1. // 1.1.
#include "RegionHillsLayer.h" #include "RegionHillsLayer.h"