forked from Mirrorlandia_minetest/minetest
Move biome calculation to BiomeGen
BiomeGen defines an interface that, given a set of BiomeParams, computes biomes for a given area using the algorithm implemented by that specific BiomeGen. This abstracts away the old system where each mapgen supplied the noises required for biome generation.
This commit is contained in:
parent
fa6b21a15b
commit
76f4856479
@ -181,8 +181,6 @@ EmergeManager::~EmergeManager()
|
||||
delete oremgr;
|
||||
delete decomgr;
|
||||
delete schemmgr;
|
||||
|
||||
delete params.sparams;
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,10 +76,9 @@ Mapgen::Mapgen()
|
||||
|
||||
vm = NULL;
|
||||
ndef = NULL;
|
||||
heightmap = NULL;
|
||||
biomegen = NULL;
|
||||
biomemap = NULL;
|
||||
heatmap = NULL;
|
||||
humidmap = NULL;
|
||||
heightmap = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -94,11 +93,10 @@ Mapgen::Mapgen(int mapgenid, MapgenParams *params, EmergeManager *emerge) :
|
||||
csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE);
|
||||
|
||||
vm = NULL;
|
||||
ndef = NULL;
|
||||
heightmap = NULL;
|
||||
ndef = emerge->ndef;
|
||||
biomegen = NULL;
|
||||
biomemap = NULL;
|
||||
heatmap = NULL;
|
||||
humidmap = NULL;
|
||||
heightmap = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -444,6 +442,14 @@ void GenerateNotifier::getEvents(
|
||||
//// MapgenParams
|
||||
////
|
||||
|
||||
|
||||
MapgenParams::~MapgenParams()
|
||||
{
|
||||
delete bparams;
|
||||
delete sparams;
|
||||
}
|
||||
|
||||
|
||||
void MapgenParams::load(const Settings &settings)
|
||||
{
|
||||
std::string seed_str;
|
||||
@ -458,10 +464,13 @@ void MapgenParams::load(const Settings &settings)
|
||||
settings.getS16NoEx("water_level", water_level);
|
||||
settings.getS16NoEx("chunksize", chunksize);
|
||||
settings.getFlagStrNoEx("mg_flags", flags, flagdesc_mapgen);
|
||||
settings.getNoiseParams("mg_biome_np_heat", np_biome_heat);
|
||||
settings.getNoiseParams("mg_biome_np_heat_blend", np_biome_heat_blend);
|
||||
settings.getNoiseParams("mg_biome_np_humidity", np_biome_humidity);
|
||||
settings.getNoiseParams("mg_biome_np_humidity_blend", np_biome_humidity_blend);
|
||||
|
||||
delete bparams;
|
||||
bparams = BiomeManager::createBiomeParams(BIOMEGEN_ORIGINAL);
|
||||
if (bparams) {
|
||||
bparams->readParams(&settings);
|
||||
bparams->seed = seed;
|
||||
}
|
||||
|
||||
delete sparams;
|
||||
MapgenFactory *mgfactory = EmergeManager::getMapgenFactory(mg_name);
|
||||
@ -479,10 +488,9 @@ void MapgenParams::save(Settings &settings) const
|
||||
settings.setS16("water_level", water_level);
|
||||
settings.setS16("chunksize", chunksize);
|
||||
settings.setFlagStr("mg_flags", flags, flagdesc_mapgen, U32_MAX);
|
||||
settings.setNoiseParams("mg_biome_np_heat", np_biome_heat);
|
||||
settings.setNoiseParams("mg_biome_np_heat_blend", np_biome_heat_blend);
|
||||
settings.setNoiseParams("mg_biome_np_humidity", np_biome_humidity);
|
||||
settings.setNoiseParams("mg_biome_np_humidity_blend", np_biome_humidity_blend);
|
||||
|
||||
if (bparams)
|
||||
bparams->writeParams(&settings);
|
||||
|
||||
if (sparams)
|
||||
sparams->writeParams(&settings);
|
||||
|
21
src/mapgen.h
21
src/mapgen.h
@ -44,6 +44,8 @@ extern FlagDesc flagdesc_mapgen[];
|
||||
extern FlagDesc flagdesc_gennotify[];
|
||||
|
||||
class Biome;
|
||||
class BiomeGen;
|
||||
struct BiomeParams;
|
||||
class EmergeManager;
|
||||
class MapBlock;
|
||||
class VoxelManipulator;
|
||||
@ -115,11 +117,7 @@ struct MapgenParams {
|
||||
s16 water_level;
|
||||
u32 flags;
|
||||
|
||||
NoiseParams np_biome_heat;
|
||||
NoiseParams np_biome_heat_blend;
|
||||
NoiseParams np_biome_humidity;
|
||||
NoiseParams np_biome_humidity_blend;
|
||||
|
||||
BiomeParams *bparams;
|
||||
MapgenSpecificParams *sparams;
|
||||
|
||||
MapgenParams() :
|
||||
@ -128,12 +126,12 @@ struct MapgenParams {
|
||||
seed(0),
|
||||
water_level(1),
|
||||
flags(MG_CAVES | MG_LIGHT | MG_DECORATIONS),
|
||||
np_biome_heat(NoiseParams(50, 50, v3f(750.0, 750.0, 750.0), 5349, 3, 0.5, 2.0)),
|
||||
np_biome_heat_blend(NoiseParams(0, 1.5, v3f(8.0, 8.0, 8.0), 13, 2, 1.0, 2.0)),
|
||||
np_biome_humidity(NoiseParams(50, 50, v3f(750.0, 750.0, 750.0), 842, 3, 0.5, 2.0)),
|
||||
np_biome_humidity_blend(NoiseParams(0, 1.5, v3f(8.0, 8.0, 8.0), 90003, 2, 1.0, 2.0)),
|
||||
bparams(NULL),
|
||||
sparams(NULL)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~MapgenParams();
|
||||
|
||||
void load(const Settings &settings);
|
||||
void save(Settings &settings) const;
|
||||
@ -153,10 +151,9 @@ public:
|
||||
u32 blockseed;
|
||||
s16 *heightmap;
|
||||
u8 *biomemap;
|
||||
float *heatmap;
|
||||
float *humidmap;
|
||||
v3s16 csize;
|
||||
|
||||
BiomeGen *biomegen;
|
||||
GenerateNotifier gennotify;
|
||||
|
||||
Mapgen();
|
||||
|
@ -61,10 +61,7 @@ MapgenFlat::MapgenFlat(int mapgenid, MapgenParams *params, EmergeManager *emerge
|
||||
// 1-down overgeneration
|
||||
this->zstride_1d = csize.X * (csize.Y + 1);
|
||||
|
||||
this->biomemap = new u8[csize.X * csize.Z];
|
||||
this->heightmap = new s16[csize.X * csize.Z];
|
||||
this->heatmap = NULL;
|
||||
this->humidmap = NULL;
|
||||
|
||||
MapgenFlatParams *sp = (MapgenFlatParams *)params->sparams;
|
||||
|
||||
@ -86,15 +83,12 @@ MapgenFlat::MapgenFlat(int mapgenid, MapgenParams *params, EmergeManager *emerge
|
||||
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
|
||||
//// Biome noise
|
||||
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
||||
noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
|
||||
noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
|
||||
noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
|
||||
//// Initialize biome generator
|
||||
biomegen = emerge->biomemgr->createBiomeGen(
|
||||
BIOMEGEN_ORIGINAL, params->bparams, csize);
|
||||
biomemap = biomegen->biomemap;
|
||||
|
||||
//// Resolve nodes to be used
|
||||
INodeDefManager *ndef = emerge->ndef;
|
||||
|
||||
c_stone = ndef->getId("mapgen_stone");
|
||||
c_water_source = ndef->getId("mapgen_water_source");
|
||||
c_lava_source = ndef->getId("mapgen_lava_source");
|
||||
@ -128,13 +122,9 @@ MapgenFlat::~MapgenFlat()
|
||||
delete noise_cave1;
|
||||
delete noise_cave2;
|
||||
|
||||
delete noise_heat;
|
||||
delete noise_humidity;
|
||||
delete noise_heat_blend;
|
||||
delete noise_humidity_blend;
|
||||
delete biomegen;
|
||||
|
||||
delete[] heightmap;
|
||||
delete[] biomemap;
|
||||
}
|
||||
|
||||
|
||||
@ -252,12 +242,10 @@ void MapgenFlat::makeChunk(BlockMakeData *data)
|
||||
// Create heightmap
|
||||
updateHeightmap(node_min, node_max);
|
||||
|
||||
// Create biomemap at heightmap surface
|
||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||
noise_humidity->result, heightmap, biomemap);
|
||||
|
||||
// Actually place the biome-specific nodes
|
||||
MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result);
|
||||
// Init biome generator, place biome-specific nodes, and build biomemap
|
||||
biomegen->calcBiomeNoise(node_min);
|
||||
biomegen->getBiomes(heightmap);
|
||||
MgStoneType stone_type = generateBiomes();
|
||||
|
||||
if (flags & MG_CAVES)
|
||||
generateCaves(stone_surface_max_y);
|
||||
@ -343,18 +331,7 @@ void MapgenFlat::calculateNoise()
|
||||
// only if solid terrain is present in mapchunk
|
||||
|
||||
noise_filler_depth->perlinMap2D(x, z);
|
||||
noise_heat->perlinMap2D(x, z);
|
||||
noise_humidity->perlinMap2D(x, z);
|
||||
noise_heat_blend->perlinMap2D(x, z);
|
||||
noise_humidity_blend->perlinMap2D(x, z);
|
||||
|
||||
for (s32 i = 0; i < csize.X * csize.Z; i++) {
|
||||
noise_heat->result[i] += noise_heat_blend->result[i];
|
||||
noise_humidity->result[i] += noise_humidity_blend->result[i];
|
||||
}
|
||||
|
||||
heatmap = noise_heat->result;
|
||||
humidmap = noise_humidity->result;
|
||||
//printf("calculateNoise: %dus\n", t.stop());
|
||||
}
|
||||
|
||||
@ -406,7 +383,7 @@ s16 MapgenFlat::generateTerrain()
|
||||
}
|
||||
|
||||
|
||||
MgStoneType MapgenFlat::generateBiomes(float *heat_map, float *humidity_map)
|
||||
MgStoneType MapgenFlat::generateBiomes()
|
||||
{
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
u32 index = 0;
|
||||
@ -443,7 +420,8 @@ MgStoneType MapgenFlat::generateBiomes(float *heat_map, float *humidity_map)
|
||||
// 3. When stone or water is detected but biome has not yet been calculated.
|
||||
if ((c == c_stone && (air_above || water_above || !biome)) ||
|
||||
(c == c_water_source && (air_above || !biome))) {
|
||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||
biome = biomegen->getBiomeAtIndex(index, y);
|
||||
|
||||
depth_top = biome->depth_top;
|
||||
base_filler = MYMAX(depth_top + biome->depth_filler
|
||||
+ noise_filler_depth->result[index], 0);
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
int getSpawnLevelAtPoint(v2s16 p);
|
||||
void calculateNoise();
|
||||
s16 generateTerrain();
|
||||
MgStoneType generateBiomes(float *heat_map, float *humidity_map);
|
||||
MgStoneType generateBiomes();
|
||||
void dustTopNodes();
|
||||
void generateCaves(s16 max_stone_y);
|
||||
};
|
||||
|
@ -59,10 +59,7 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
|
||||
// 1-down overgeneration
|
||||
this->zstride_1d = csize.X * (csize.Y + 1);
|
||||
|
||||
this->biomemap = new u8[csize.X * csize.Z];
|
||||
this->heightmap = new s16[csize.X * csize.Z];
|
||||
this->heatmap = NULL;
|
||||
this->humidmap = NULL;
|
||||
|
||||
MapgenFractalParams *sp = (MapgenFractalParams *)params->sparams;
|
||||
|
||||
@ -87,18 +84,15 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
|
||||
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
|
||||
//// Biome noise
|
||||
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
||||
noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
|
||||
noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
|
||||
noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
|
||||
//// Initialize biome generator
|
||||
biomegen = emerge->biomemgr->createBiomeGen(
|
||||
BIOMEGEN_ORIGINAL, params->bparams, csize);
|
||||
biomemap = biomegen->biomemap;
|
||||
|
||||
this->formula = fractal / 2 + fractal % 2;
|
||||
this->julia = fractal % 2 == 0;
|
||||
|
||||
//// Resolve nodes to be used
|
||||
INodeDefManager *ndef = emerge->ndef;
|
||||
|
||||
c_stone = ndef->getId("mapgen_stone");
|
||||
c_water_source = ndef->getId("mapgen_water_source");
|
||||
c_lava_source = ndef->getId("mapgen_lava_source");
|
||||
@ -132,13 +126,9 @@ MapgenFractal::~MapgenFractal()
|
||||
delete noise_cave1;
|
||||
delete noise_cave2;
|
||||
|
||||
delete noise_heat;
|
||||
delete noise_humidity;
|
||||
delete noise_heat_blend;
|
||||
delete noise_humidity_blend;
|
||||
delete biomegen;
|
||||
|
||||
delete[] heightmap;
|
||||
delete[] biomemap;
|
||||
}
|
||||
|
||||
|
||||
@ -268,12 +258,10 @@ void MapgenFractal::makeChunk(BlockMakeData *data)
|
||||
// Create heightmap
|
||||
updateHeightmap(node_min, node_max);
|
||||
|
||||
// Create biomemap at heightmap surface
|
||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||
noise_humidity->result, heightmap, biomemap);
|
||||
|
||||
// Actually place the biome-specific nodes
|
||||
MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result);
|
||||
// Init biome generator, place biome-specific nodes, and build biomemap
|
||||
biomegen->calcBiomeNoise(node_min);
|
||||
biomegen->getBiomes(heightmap);
|
||||
MgStoneType stone_type = generateBiomes();
|
||||
|
||||
if (flags & MG_CAVES)
|
||||
generateCaves(stone_surface_max_y);
|
||||
@ -358,18 +346,7 @@ void MapgenFractal::calculateNoise()
|
||||
// only if solid terrain is present in mapchunk
|
||||
|
||||
noise_filler_depth->perlinMap2D(x, z);
|
||||
noise_heat->perlinMap2D(x, z);
|
||||
noise_humidity->perlinMap2D(x, z);
|
||||
noise_heat_blend->perlinMap2D(x, z);
|
||||
noise_humidity_blend->perlinMap2D(x, z);
|
||||
|
||||
for (s32 i = 0; i < csize.X * csize.Z; i++) {
|
||||
noise_heat->result[i] += noise_heat_blend->result[i];
|
||||
noise_humidity->result[i] += noise_humidity_blend->result[i];
|
||||
}
|
||||
|
||||
heatmap = noise_heat->result;
|
||||
humidmap = noise_humidity->result;
|
||||
//printf("calculateNoise: %dus\n", t.stop());
|
||||
}
|
||||
|
||||
@ -530,7 +507,7 @@ s16 MapgenFractal::generateTerrain()
|
||||
}
|
||||
|
||||
|
||||
MgStoneType MapgenFractal::generateBiomes(float *heat_map, float *humidity_map)
|
||||
MgStoneType MapgenFractal::generateBiomes()
|
||||
{
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
u32 index = 0;
|
||||
@ -567,7 +544,8 @@ MgStoneType MapgenFractal::generateBiomes(float *heat_map, float *humidity_map)
|
||||
// 3. When stone or water is detected but biome has not yet been calculated.
|
||||
if ((c == c_stone && (air_above || water_above || !biome)) ||
|
||||
(c == c_water_source && (air_above || !biome))) {
|
||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||
biome = biomegen->getBiomeAtIndex(index, y);
|
||||
|
||||
depth_top = biome->depth_top;
|
||||
base_filler = MYMAX(depth_top + biome->depth_filler
|
||||
+ noise_filler_depth->result[index], 0);
|
||||
|
@ -88,11 +88,6 @@ public:
|
||||
Noise *noise_cave1;
|
||||
Noise *noise_cave2;
|
||||
|
||||
Noise *noise_heat;
|
||||
Noise *noise_humidity;
|
||||
Noise *noise_heat_blend;
|
||||
Noise *noise_humidity_blend;
|
||||
|
||||
content_t c_stone;
|
||||
content_t c_water_source;
|
||||
content_t c_lava_source;
|
||||
@ -114,7 +109,7 @@ public:
|
||||
void calculateNoise();
|
||||
bool getFractalAtPoint(s16 x, s16 y, s16 z);
|
||||
s16 generateTerrain();
|
||||
MgStoneType generateBiomes(float *heat_map, float *humidity_map);
|
||||
MgStoneType generateBiomes();
|
||||
void dustTopNodes();
|
||||
void generateCaves(s16 max_stone_y);
|
||||
};
|
||||
|
@ -57,10 +57,7 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||
// 1-down overgeneration
|
||||
this->zstride_1d = csize.X * (csize.Y + 1);
|
||||
|
||||
this->biomemap = new u8[csize.X * csize.Z];
|
||||
this->heightmap = new s16[csize.X * csize.Z];
|
||||
this->heatmap = NULL;
|
||||
this->humidmap = NULL;
|
||||
|
||||
MapgenV5Params *sp = (MapgenV5Params *)params->sparams;
|
||||
|
||||
@ -79,15 +76,12 @@ MapgenV5::MapgenV5(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
|
||||
// Biome noise
|
||||
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
||||
noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
|
||||
noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
|
||||
noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
|
||||
//// Initialize biome generator
|
||||
biomegen = emerge->biomemgr->createBiomeGen(
|
||||
BIOMEGEN_ORIGINAL, params->bparams, csize);
|
||||
biomemap = biomegen->biomemap;
|
||||
|
||||
//// Resolve nodes to be used
|
||||
INodeDefManager *ndef = emerge->ndef;
|
||||
|
||||
c_stone = ndef->getId("mapgen_stone");
|
||||
c_water_source = ndef->getId("mapgen_water_source");
|
||||
c_lava_source = ndef->getId("mapgen_lava_source");
|
||||
@ -123,13 +117,9 @@ MapgenV5::~MapgenV5()
|
||||
delete noise_cave2;
|
||||
delete noise_ground;
|
||||
|
||||
delete noise_heat;
|
||||
delete noise_humidity;
|
||||
delete noise_heat_blend;
|
||||
delete noise_humidity_blend;
|
||||
delete biomegen;
|
||||
|
||||
delete[] heightmap;
|
||||
delete[] biomemap;
|
||||
}
|
||||
|
||||
|
||||
@ -248,12 +238,10 @@ void MapgenV5::makeChunk(BlockMakeData *data)
|
||||
// Create heightmap
|
||||
updateHeightmap(node_min, node_max);
|
||||
|
||||
// Create biomemap at heightmap surface
|
||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||
noise_humidity->result, heightmap, biomemap);
|
||||
|
||||
// Actually place the biome-specific nodes
|
||||
MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result);
|
||||
// Init biome generator, place biome-specific nodes, and build biomemap
|
||||
biomegen->calcBiomeNoise(node_min);
|
||||
biomegen->getBiomes(heightmap);
|
||||
MgStoneType stone_type = generateBiomes();
|
||||
|
||||
// Generate caves
|
||||
if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y))
|
||||
@ -343,18 +331,7 @@ void MapgenV5::calculateNoise()
|
||||
// only if solid terrain is present in mapchunk
|
||||
|
||||
noise_filler_depth->perlinMap2D(x, z);
|
||||
noise_heat->perlinMap2D(x, z);
|
||||
noise_humidity->perlinMap2D(x, z);
|
||||
noise_heat_blend->perlinMap2D(x, z);
|
||||
noise_humidity_blend->perlinMap2D(x, z);
|
||||
|
||||
for (s32 i = 0; i < csize.X * csize.Z; i++) {
|
||||
noise_heat->result[i] += noise_heat_blend->result[i];
|
||||
noise_humidity->result[i] += noise_humidity_blend->result[i];
|
||||
}
|
||||
|
||||
heatmap = noise_heat->result;
|
||||
humidmap = noise_humidity->result;
|
||||
//printf("calculateNoise: %dus\n", t.stop());
|
||||
}
|
||||
|
||||
@ -416,7 +393,7 @@ int MapgenV5::generateBaseTerrain()
|
||||
}
|
||||
|
||||
|
||||
MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
|
||||
MgStoneType MapgenV5::generateBiomes()
|
||||
{
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
u32 index = 0;
|
||||
@ -452,7 +429,8 @@ MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
|
||||
// 3. When stone or water is detected but biome has not yet been calculated.
|
||||
if ((c == c_stone && (air_above || water_above || !biome)) ||
|
||||
(c == c_water_source && (air_above || !biome))) {
|
||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||
biome = biomegen->getBiomeAtIndex(index, y);
|
||||
|
||||
depth_top = biome->depth_top;
|
||||
base_filler = MYMAX(depth_top + biome->depth_filler
|
||||
+ noise_filler_depth->result[index], 0);
|
||||
|
@ -70,11 +70,6 @@ public:
|
||||
Noise *noise_cave2;
|
||||
Noise *noise_ground;
|
||||
|
||||
Noise *noise_heat;
|
||||
Noise *noise_humidity;
|
||||
Noise *noise_heat_blend;
|
||||
Noise *noise_humidity_blend;
|
||||
|
||||
content_t c_stone;
|
||||
content_t c_water_source;
|
||||
content_t c_lava_source;
|
||||
@ -95,7 +90,7 @@ public:
|
||||
int getSpawnLevelAtPoint(v2s16 p);
|
||||
void calculateNoise();
|
||||
int generateBaseTerrain();
|
||||
MgStoneType generateBiomes(float *heat_map, float *humidity_map);
|
||||
MgStoneType generateBiomes();
|
||||
void generateCaves(int max_stone_y);
|
||||
void dustTopNodes();
|
||||
};
|
||||
|
@ -64,10 +64,7 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||
// 1-down overgeneration
|
||||
this->zstride_1d = csize.X * (csize.Y + 1);
|
||||
|
||||
this->biomemap = new u8[csize.X * csize.Z];
|
||||
this->heightmap = new s16[csize.X * csize.Z];
|
||||
this->heatmap = NULL;
|
||||
this->humidmap = NULL;
|
||||
this->ridge_heightmap = new s16[csize.X * csize.Z];
|
||||
|
||||
MapgenV7Params *sp = (MapgenV7Params *)params->sparams;
|
||||
@ -92,15 +89,13 @@ MapgenV7::MapgenV7(int mapgenid, MapgenParams *params, EmergeManager *emerge)
|
||||
noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
|
||||
//// Biome noise
|
||||
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
||||
noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
|
||||
noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
|
||||
noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
|
||||
// TODO(hmmmm): should we have a way to disable biomemanager biomes?
|
||||
//// Initialize biome generator
|
||||
biomegen = emerge->biomemgr->createBiomeGen(
|
||||
BIOMEGEN_ORIGINAL, params->bparams, csize);
|
||||
biomemap = biomegen->biomemap;
|
||||
|
||||
//// Resolve nodes to be used
|
||||
INodeDefManager *ndef = emerge->ndef;
|
||||
|
||||
c_stone = ndef->getId("mapgen_stone");
|
||||
c_water_source = ndef->getId("mapgen_water_source");
|
||||
c_lava_source = ndef->getId("mapgen_lava_source");
|
||||
@ -141,14 +136,10 @@ MapgenV7::~MapgenV7()
|
||||
delete noise_cave1;
|
||||
delete noise_cave2;
|
||||
|
||||
delete noise_heat;
|
||||
delete noise_humidity;
|
||||
delete noise_heat_blend;
|
||||
delete noise_humidity_blend;
|
||||
delete biomegen;
|
||||
|
||||
delete[] ridge_heightmap;
|
||||
delete[] heightmap;
|
||||
delete[] biomemap;
|
||||
}
|
||||
|
||||
|
||||
@ -279,12 +270,10 @@ void MapgenV7::makeChunk(BlockMakeData *data)
|
||||
// Update heightmap to include mountain terrain
|
||||
updateHeightmap(node_min, node_max);
|
||||
|
||||
// Create biomemap at heightmap surface
|
||||
bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result,
|
||||
noise_humidity->result, heightmap, biomemap);
|
||||
|
||||
// Actually place the biome-specific nodes
|
||||
MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result);
|
||||
// Init biome generator, place biome-specific nodes, and build biomemap
|
||||
biomegen->calcBiomeNoise(node_min);
|
||||
biomegen->getBiomes(heightmap);
|
||||
MgStoneType stone_type = generateBiomes();
|
||||
|
||||
if (flags & MG_CAVES)
|
||||
generateCaves(stone_surface_max_y);
|
||||
@ -384,35 +373,10 @@ void MapgenV7::calculateNoise()
|
||||
// Cave noises are calculated in generateCaves()
|
||||
// only if solid terrain is present in mapchunk
|
||||
|
||||
noise_filler_depth->perlinMap2D(x, z);
|
||||
noise_heat->perlinMap2D(x, z);
|
||||
noise_humidity->perlinMap2D(x, z);
|
||||
noise_heat_blend->perlinMap2D(x, z);
|
||||
noise_humidity_blend->perlinMap2D(x, z);
|
||||
|
||||
for (s32 i = 0; i < csize.X * csize.Z; i++) {
|
||||
noise_heat->result[i] += noise_heat_blend->result[i];
|
||||
noise_humidity->result[i] += noise_humidity_blend->result[i];
|
||||
}
|
||||
|
||||
heatmap = noise_heat->result;
|
||||
humidmap = noise_humidity->result;
|
||||
//printf("calculateNoise: %dus\n", t.stop());
|
||||
}
|
||||
|
||||
|
||||
Biome *MapgenV7::getBiomeAtPoint(v3s16 p)
|
||||
{
|
||||
float heat = NoisePerlin2D(&noise_heat->np, p.X, p.Z, seed) +
|
||||
NoisePerlin2D(&noise_heat_blend->np, p.X, p.Z, seed);
|
||||
float humidity = NoisePerlin2D(&noise_humidity->np, p.X, p.Z, seed) +
|
||||
NoisePerlin2D(&noise_humidity_blend->np, p.X, p.Z, seed);
|
||||
s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Z);
|
||||
|
||||
return bmgr->getBiome(heat, humidity, groundlevel);
|
||||
}
|
||||
|
||||
|
||||
float MapgenV7::baseTerrainLevelAtPoint(s16 x, s16 z)
|
||||
{
|
||||
float hselect = NoisePerlin2D(&noise_height_select->np, x, z, seed);
|
||||
@ -553,7 +517,7 @@ void MapgenV7::generateRidgeTerrain()
|
||||
}
|
||||
|
||||
|
||||
MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
|
||||
MgStoneType MapgenV7::generateBiomes()
|
||||
{
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
u32 index = 0;
|
||||
@ -589,7 +553,8 @@ MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
|
||||
// 3. When stone or water is detected but biome has not yet been calculated.
|
||||
if ((c == c_stone && (air_above || water_above || !biome)) ||
|
||||
(c == c_water_source && (air_above || !biome))) {
|
||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||
biome = biomegen->getBiomeAtIndex(index, y);
|
||||
|
||||
depth_top = biome->depth_top;
|
||||
base_filler = MYMAX(depth_top + biome->depth_filler
|
||||
+ noise_filler_depth->result[index], 0);
|
||||
|
@ -84,11 +84,6 @@ public:
|
||||
Noise *noise_cave1;
|
||||
Noise *noise_cave2;
|
||||
|
||||
Noise *noise_heat;
|
||||
Noise *noise_humidity;
|
||||
Noise *noise_heat_blend;
|
||||
Noise *noise_humidity_blend;
|
||||
|
||||
content_t c_stone;
|
||||
content_t c_water_source;
|
||||
content_t c_lava_source;
|
||||
@ -107,7 +102,6 @@ public:
|
||||
|
||||
virtual void makeChunk(BlockMakeData *data);
|
||||
int getSpawnLevelAtPoint(v2s16 p);
|
||||
Biome *getBiomeAtPoint(v3s16 p);
|
||||
|
||||
float baseTerrainLevelAtPoint(s16 x, s16 z);
|
||||
float baseTerrainLevelFromMap(int index);
|
||||
@ -119,7 +113,7 @@ public:
|
||||
int generateTerrain();
|
||||
void generateRidgeTerrain();
|
||||
|
||||
MgStoneType generateBiomes(float *heat_map, float *humidity_map);
|
||||
MgStoneType generateBiomes();
|
||||
void dustTopNodes();
|
||||
|
||||
void generateCaves(s16 max_stone_y);
|
||||
|
@ -77,15 +77,13 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
|
||||
// 1-down overgeneration
|
||||
this->zstride_1d = csize.X * (csize.Y + 1);
|
||||
|
||||
this->biomemap = new u8[csize.X * csize.Z];
|
||||
this->heightmap = new s16[csize.X * csize.Z];
|
||||
this->heatmap = NULL;
|
||||
this->humidmap = NULL;
|
||||
|
||||
this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
|
||||
g_settings->getU16("map_generation_limit"));
|
||||
|
||||
MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
|
||||
BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
|
||||
|
||||
this->spflags = sp->spflags;
|
||||
this->altitude_chill = sp->altitude_chill;
|
||||
@ -113,15 +111,16 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
|
||||
noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
noise_massive_caves = new Noise(&sp->np_massive_caves, seed, csize.X, csize.Y + 1, csize.Z);
|
||||
|
||||
//// Biome noise
|
||||
noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
|
||||
noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
|
||||
noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
|
||||
noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
|
||||
//// Initialize biome generator
|
||||
// NOTE: valleys mapgen can only use BiomeGenOriginal
|
||||
biomegen = emerge->biomemgr->createBiomeGen(
|
||||
BIOMEGEN_ORIGINAL, params->bparams, csize);
|
||||
biomemap = biomegen->biomemap;
|
||||
m_bgen = (BiomeGenOriginal *)biomegen;
|
||||
|
||||
this->humid_rivers = (spflags & MGVALLEYS_HUMID_RIVERS);
|
||||
this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
|
||||
this->humidity_adjust = params->np_biome_humidity.offset - 50.f;
|
||||
this->humidity_adjust = bp->np_humidity.offset - 50.f;
|
||||
|
||||
// a small chance of overflows if the settings are very high
|
||||
this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
|
||||
@ -130,8 +129,6 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
|
||||
tcave_cache = new float[csize.Y + 2];
|
||||
|
||||
//// Resolve nodes to be used
|
||||
INodeDefManager *ndef = emerge->ndef;
|
||||
|
||||
c_cobble = ndef->getId("mapgen_cobble");
|
||||
c_desert_stone = ndef->getId("mapgen_desert_stone");
|
||||
c_dirt = ndef->getId("mapgen_dirt");
|
||||
@ -174,12 +171,8 @@ MapgenValleys::~MapgenValleys()
|
||||
delete noise_valley_depth;
|
||||
delete noise_valley_profile;
|
||||
|
||||
delete noise_heat;
|
||||
delete noise_heat_blend;
|
||||
delete noise_humidity;
|
||||
delete noise_humidity_blend;
|
||||
delete biomegen;
|
||||
|
||||
delete[] biomemap;
|
||||
delete[] heightmap;
|
||||
delete[] tcave_cache;
|
||||
}
|
||||
@ -293,14 +286,19 @@ void MapgenValleys::makeChunk(BlockMakeData *data)
|
||||
// Generate noise maps and base terrain height.
|
||||
calculateNoise();
|
||||
|
||||
// Generate biome noises. Note this must be executed strictly before
|
||||
// generateTerrain, because generateTerrain depends on intermediate
|
||||
// biome-related noises.
|
||||
biomegen->calcBiomeNoise(node_min);
|
||||
|
||||
// Generate base terrain with initial heightmaps
|
||||
s16 stone_surface_max_y = generateTerrain();
|
||||
|
||||
// Create biomemap at heightmap surface
|
||||
bmgr->calcBiomes(csize.X, csize.Z, heatmap, humidmap, heightmap, biomemap);
|
||||
// Build biomemap
|
||||
biomegen->getBiomes(heightmap);
|
||||
|
||||
// Actually place the biome-specific nodes
|
||||
MgStoneType stone_type = generateBiomes(heatmap, humidmap);
|
||||
// Place biome-specific nodes
|
||||
MgStoneType stone_type = generateBiomes();
|
||||
|
||||
// Cave creation.
|
||||
if (flags & MG_CAVES)
|
||||
@ -391,10 +389,6 @@ void MapgenValleys::calculateNoise()
|
||||
//TimeTaker tcn("actualNoise");
|
||||
|
||||
noise_filler_depth->perlinMap2D(x, z);
|
||||
noise_heat_blend->perlinMap2D(x, z);
|
||||
noise_heat->perlinMap2D(x, z);
|
||||
noise_humidity_blend->perlinMap2D(x, z);
|
||||
noise_humidity->perlinMap2D(x, z);
|
||||
noise_inter_valley_slope->perlinMap2D(x, z);
|
||||
noise_rivers->perlinMap2D(x, z);
|
||||
noise_terrain_height->perlinMap2D(x, z);
|
||||
@ -418,9 +412,8 @@ void MapgenValleys::calculateNoise()
|
||||
}
|
||||
|
||||
for (s32 index = 0; index < csize.X * csize.Z; index++) {
|
||||
noise_heat->result[index] += noise_heat_blend->result[index] + heat_offset;
|
||||
noise_humidity->result[index] *= humidity_scale;
|
||||
noise_humidity->result[index] += noise_humidity_blend->result[index];
|
||||
m_bgen->heatmap[index] += heat_offset;
|
||||
m_bgen->humidmap[index] *= humidity_scale;
|
||||
}
|
||||
|
||||
TerrainNoise tn;
|
||||
@ -450,9 +443,6 @@ void MapgenValleys::calculateNoise()
|
||||
float mount = terrainLevelFromNoise(&tn);
|
||||
noise_terrain_height->result[index] = mount;
|
||||
}
|
||||
|
||||
heatmap = noise_heat->result;
|
||||
humidmap = noise_humidity->result;
|
||||
}
|
||||
|
||||
|
||||
@ -596,7 +586,7 @@ int MapgenValleys::generateTerrain()
|
||||
float river_y = noise_rivers->result[index_2d];
|
||||
float surface_y = noise_terrain_height->result[index_2d];
|
||||
float slope = noise_inter_valley_slope->result[index_2d];
|
||||
float t_heat = noise_heat->result[index_2d];
|
||||
float t_heat = m_bgen->heatmap[index_2d];
|
||||
|
||||
heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
|
||||
|
||||
@ -610,7 +600,7 @@ int MapgenValleys::generateTerrain()
|
||||
t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill;
|
||||
|
||||
// If humidity is low or heat is high, lower the water table.
|
||||
float delta = noise_humidity->result[index_2d] - 50.f;
|
||||
float delta = m_bgen->humidmap[index_2d] - 50.f;
|
||||
if (delta < 0.f) {
|
||||
float t_evap = (t_heat - 32.f) / evaporation;
|
||||
river_y += delta * MYMAX(t_evap, 0.08f);
|
||||
@ -672,7 +662,7 @@ int MapgenValleys::generateTerrain()
|
||||
// Use base ground (water table) in a riverbed, to
|
||||
// avoid an unnatural rise in humidity.
|
||||
float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
|
||||
float humid = noise_humidity->result[index_2d];
|
||||
float humid = m_bgen->humidmap[index_2d];
|
||||
float water_depth = (t_alt - river_y) / humidity_dropoff;
|
||||
humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f));
|
||||
|
||||
@ -683,7 +673,7 @@ int MapgenValleys::generateTerrain()
|
||||
if (t_alt > 0.f)
|
||||
humid -= alt_to_humid * t_alt / altitude_chill;
|
||||
|
||||
noise_humidity->result[index_2d] = humid;
|
||||
m_bgen->humidmap[index_2d] = humid;
|
||||
}
|
||||
|
||||
// Assign the heat adjusted by any changed altitudes.
|
||||
@ -693,9 +683,9 @@ int MapgenValleys::generateTerrain()
|
||||
float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
|
||||
if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
|
||||
// The altitude hasn't changed. Use the first result.
|
||||
noise_heat->result[index_2d] = t_heat;
|
||||
m_bgen->heatmap[index_2d] = t_heat;
|
||||
else if (t_alt > 0.f)
|
||||
noise_heat->result[index_2d] -= alt_to_heat * t_alt / altitude_chill;
|
||||
m_bgen->heatmap[index_2d] -= alt_to_heat * t_alt / altitude_chill;
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,7 +693,7 @@ int MapgenValleys::generateTerrain()
|
||||
}
|
||||
|
||||
|
||||
MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map)
|
||||
MgStoneType MapgenValleys::generateBiomes()
|
||||
{
|
||||
v3s16 em = vm->m_area.getExtent();
|
||||
u32 index = 0;
|
||||
@ -741,7 +731,7 @@ MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map)
|
||||
|| ((c == c_water_source || c == c_river_water_source)
|
||||
&& (air_above || !biome))) {
|
||||
// Both heat and humidity have already been adjusted for altitude.
|
||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||
biome = biomegen->getBiomeAtIndex(index, y);
|
||||
|
||||
depth_top = biome->depth_top;
|
||||
base_filler = MYMAX(depth_top
|
||||
|
@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MYCUBE(x) (x) * (x) * (x)
|
||||
|
||||
class BiomeManager;
|
||||
class BiomeGenOriginal;
|
||||
|
||||
// Global profiler
|
||||
//class Profiler;
|
||||
@ -98,6 +99,7 @@ public:
|
||||
private:
|
||||
EmergeManager *m_emerge;
|
||||
BiomeManager *bmgr;
|
||||
BiomeGenOriginal *m_bgen;
|
||||
|
||||
int ystride;
|
||||
int zstride;
|
||||
@ -136,11 +138,6 @@ private:
|
||||
Noise *noise_valley_depth;
|
||||
Noise *noise_valley_profile;
|
||||
|
||||
Noise *noise_heat;
|
||||
Noise *noise_heat_blend;
|
||||
Noise *noise_humidity;
|
||||
Noise *noise_humidity_blend;
|
||||
|
||||
content_t c_cobble;
|
||||
content_t c_desert_stone;
|
||||
content_t c_dirt;
|
||||
@ -164,9 +161,7 @@ private:
|
||||
float terrainLevelFromNoise(TerrainNoise *tn);
|
||||
float adjustedTerrainLevelFromNoise(TerrainNoise *tn);
|
||||
|
||||
float humidityByTerrain(float humidity_base, float mount, float rivers, float valley);
|
||||
|
||||
MgStoneType generateBiomes(float *heat_map, float *humidity_map);
|
||||
MgStoneType generateBiomes();
|
||||
void dustTopNodes();
|
||||
|
||||
void generateCaves(s16 max_stone_y);
|
||||
|
185
src/mg_biome.cpp
185
src/mg_biome.cpp
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "util/numeric.h"
|
||||
#include "util/mathconstants.h"
|
||||
#include "porting.h"
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -63,49 +64,11 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
|
||||
}
|
||||
|
||||
|
||||
|
||||
BiomeManager::~BiomeManager()
|
||||
{
|
||||
//if (biomecache)
|
||||
// delete[] biomecache;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// just a PoC, obviously needs optimization later on (precalculate this)
|
||||
void BiomeManager::calcBiomes(s16 sx, s16 sy, float *heat_map,
|
||||
float *humidity_map, s16 *height_map, u8 *biomeid_map)
|
||||
{
|
||||
for (s32 i = 0; i != sx * sy; i++) {
|
||||
Biome *biome = getBiome(heat_map[i], humidity_map[i], height_map[i]);
|
||||
biomeid_map[i] = biome->index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Biome *BiomeManager::getBiome(float heat, float humidity, s16 y)
|
||||
{
|
||||
Biome *b, *biome_closest = NULL;
|
||||
float dist_min = FLT_MAX;
|
||||
|
||||
for (size_t i = 1; i < m_objects.size(); i++) {
|
||||
b = (Biome *)m_objects[i];
|
||||
if (!b || y > b->y_max || y < b->y_min)
|
||||
continue;
|
||||
|
||||
float d_heat = heat - b->heat_point;
|
||||
float d_humidity = humidity - b->humidity_point;
|
||||
float dist = (d_heat * d_heat) +
|
||||
(d_humidity * d_humidity);
|
||||
if (dist < dist_min) {
|
||||
dist_min = dist;
|
||||
biome_closest = b;
|
||||
}
|
||||
}
|
||||
|
||||
return biome_closest ? biome_closest : (Biome *)m_objects[0];
|
||||
}
|
||||
|
||||
void BiomeManager::clear()
|
||||
{
|
||||
EmergeManager *emerge = m_gamedef->getEmergeManager();
|
||||
@ -118,17 +81,153 @@ void BiomeManager::clear()
|
||||
}
|
||||
|
||||
// Don't delete the first biome
|
||||
for (size_t i = 1; i < m_objects.size(); i++) {
|
||||
Biome *b = (Biome *)m_objects[i];
|
||||
delete b;
|
||||
}
|
||||
for (size_t i = 1; i < m_objects.size(); i++)
|
||||
delete (Biome *)m_objects[i];
|
||||
|
||||
m_objects.resize(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BiomeParamsOriginal::readParams(const Settings *settings)
|
||||
{
|
||||
settings->getNoiseParams("mg_biome_np_heat", np_heat);
|
||||
settings->getNoiseParams("mg_biome_np_heat_blend", np_heat_blend);
|
||||
settings->getNoiseParams("mg_biome_np_humidity", np_humidity);
|
||||
settings->getNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend);
|
||||
}
|
||||
|
||||
|
||||
void BiomeParamsOriginal::writeParams(Settings *settings) const
|
||||
{
|
||||
settings->setNoiseParams("mg_biome_np_heat", np_heat);
|
||||
settings->setNoiseParams("mg_biome_np_heat_blend", np_heat_blend);
|
||||
settings->setNoiseParams("mg_biome_np_humidity", np_humidity);
|
||||
settings->setNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr,
|
||||
BiomeParamsOriginal *params, v3s16 chunksize)
|
||||
{
|
||||
m_bmgr = biomemgr;
|
||||
m_params = params;
|
||||
m_csize = chunksize;
|
||||
|
||||
noise_heat = new Noise(¶ms->np_heat,
|
||||
params->seed, m_csize.X, m_csize.Z);
|
||||
noise_humidity = new Noise(¶ms->np_humidity,
|
||||
params->seed, m_csize.X, m_csize.Z);
|
||||
noise_heat_blend = new Noise(¶ms->np_heat_blend,
|
||||
params->seed, m_csize.X, m_csize.Z);
|
||||
noise_humidity_blend = new Noise(¶ms->np_humidity_blend,
|
||||
params->seed, m_csize.X, m_csize.Z);
|
||||
|
||||
heatmap = noise_heat->result;
|
||||
humidmap = noise_humidity->result;
|
||||
biomemap = new u8[m_csize.X * m_csize.Z];
|
||||
}
|
||||
|
||||
BiomeGenOriginal::~BiomeGenOriginal()
|
||||
{
|
||||
delete []biomemap;
|
||||
|
||||
delete noise_heat;
|
||||
delete noise_humidity;
|
||||
delete noise_heat_blend;
|
||||
delete noise_humidity_blend;
|
||||
}
|
||||
|
||||
|
||||
Biome *BiomeGenOriginal::calcBiomeAtPoint(v3s16 pos) const
|
||||
{
|
||||
float heat =
|
||||
NoisePerlin2D(&m_params->np_heat, pos.X, pos.Z, m_params->seed) +
|
||||
NoisePerlin2D(&m_params->np_heat_blend, pos.X, pos.Z, m_params->seed);
|
||||
float humidity =
|
||||
NoisePerlin2D(&m_params->np_humidity, pos.X, pos.Z, m_params->seed) +
|
||||
NoisePerlin2D(&m_params->np_humidity_blend, pos.X, pos.Z, m_params->seed);
|
||||
|
||||
return calcBiomeFromNoise(heat, humidity, pos.Y);
|
||||
}
|
||||
|
||||
|
||||
void BiomeGenOriginal::calcBiomeNoise(v3s16 pmin)
|
||||
{
|
||||
m_pmin = pmin;
|
||||
|
||||
noise_heat->perlinMap2D(pmin.X, pmin.Z);
|
||||
noise_humidity->perlinMap2D(pmin.X, pmin.Z);
|
||||
noise_heat_blend->perlinMap2D(pmin.X, pmin.Z);
|
||||
noise_humidity_blend->perlinMap2D(pmin.X, pmin.Z);
|
||||
|
||||
for (s32 i = 0; i < m_csize.X * m_csize.Z; i++) {
|
||||
noise_heat->result[i] += noise_heat_blend->result[i];
|
||||
noise_humidity->result[i] += noise_humidity_blend->result[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u8 *BiomeGenOriginal::getBiomes(s16 *heightmap)
|
||||
{
|
||||
for (s32 i = 0; i != m_csize.X * m_csize.Z; i++) {
|
||||
Biome *biome = calcBiomeFromNoise(
|
||||
noise_heat->result[i],
|
||||
noise_humidity->result[i],
|
||||
heightmap[i]);
|
||||
|
||||
biomemap[i] = biome->index;
|
||||
}
|
||||
|
||||
return biomemap;
|
||||
}
|
||||
|
||||
|
||||
Biome *BiomeGenOriginal::getBiomeAtPoint(v3s16 pos) const
|
||||
{
|
||||
return getBiomeAtIndex(
|
||||
(pos.Z - m_pmin.Z) * m_csize.X + (pos.X - m_pmin.X),
|
||||
pos.Y);
|
||||
}
|
||||
|
||||
|
||||
Biome *BiomeGenOriginal::getBiomeAtIndex(size_t index, s16 y) const
|
||||
{
|
||||
return calcBiomeFromNoise(
|
||||
noise_heat->result[index],
|
||||
noise_humidity->result[index],
|
||||
y);
|
||||
}
|
||||
|
||||
|
||||
Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, s16 y) const
|
||||
{
|
||||
Biome *b, *biome_closest = NULL;
|
||||
float dist_min = FLT_MAX;
|
||||
|
||||
for (size_t i = 1; i < m_bmgr->getNumObjects(); i++) {
|
||||
b = (Biome *)m_bmgr->getRaw(i);
|
||||
if (!b || y > b->y_max || y < b->y_min)
|
||||
continue;
|
||||
|
||||
float d_heat = heat - b->heat_point;
|
||||
float d_humidity = humidity - b->humidity_point;
|
||||
float dist = (d_heat * d_heat) +
|
||||
(d_humidity * d_humidity);
|
||||
if (dist < dist_min) {
|
||||
dist_min = dist;
|
||||
biome_closest = b;
|
||||
}
|
||||
}
|
||||
|
||||
return biome_closest ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Biome::resolveNodeNames()
|
||||
{
|
||||
|
155
src/mg_biome.h
155
src/mg_biome.h
@ -22,6 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "objdef.h"
|
||||
#include "nodedef.h"
|
||||
#include "noise.h"
|
||||
|
||||
class Settings;
|
||||
class BiomeManager;
|
||||
|
||||
////
|
||||
//// Biome
|
||||
////
|
||||
|
||||
#define BIOME_NONE ((u8)0)
|
||||
|
||||
enum BiomeType
|
||||
{
|
||||
@ -56,10 +66,122 @@ public:
|
||||
virtual void resolveNodeNames();
|
||||
};
|
||||
|
||||
|
||||
////
|
||||
//// BiomeGen
|
||||
////
|
||||
|
||||
enum BiomeGenType {
|
||||
BIOMEGEN_ORIGINAL,
|
||||
};
|
||||
|
||||
struct BiomeParams {
|
||||
virtual void readParams(const Settings *settings) = 0;
|
||||
virtual void writeParams(Settings *settings) const = 0;
|
||||
virtual ~BiomeParams() {}
|
||||
|
||||
int seed;
|
||||
};
|
||||
|
||||
class BiomeGen {
|
||||
public:
|
||||
virtual ~BiomeGen() {}
|
||||
virtual BiomeGenType getType() const = 0;
|
||||
|
||||
// Calculates the biome at the exact position provided. This function can
|
||||
// be called at any time, but may be less efficient than the latter methods,
|
||||
// depending on implementation.
|
||||
virtual Biome *calcBiomeAtPoint(v3s16 pos) const = 0;
|
||||
|
||||
// Computes any intermediate results needed for biome generation. Must be
|
||||
// called before using any of: getBiomes, getBiomeAtPoint, or getBiomeAtIndex.
|
||||
// Calling this invalidates the previous results stored in biomemap.
|
||||
virtual void calcBiomeNoise(v3s16 pmin) = 0;
|
||||
|
||||
// Gets all biomes in current chunk using each corresponding element of
|
||||
// heightmap as the y position, then stores the results by biome index in
|
||||
// biomemap (also returned)
|
||||
virtual u8 *getBiomes(s16 *heightmap) = 0;
|
||||
|
||||
// Gets a single biome at the specified position, which must be contained
|
||||
// in the region formed by m_pmin and (m_pmin + m_csize - 1).
|
||||
virtual Biome *getBiomeAtPoint(v3s16 pos) const = 0;
|
||||
|
||||
// Same as above, but uses a raw numeric index correlating to the (x,z) position.
|
||||
virtual Biome *getBiomeAtIndex(size_t index, s16 y) const = 0;
|
||||
|
||||
// Result of calcBiomes bulk computation.
|
||||
u8 *biomemap;
|
||||
|
||||
protected:
|
||||
BiomeManager *m_bmgr;
|
||||
v3s16 m_pmin;
|
||||
v3s16 m_csize;
|
||||
};
|
||||
|
||||
|
||||
////
|
||||
//// BiomeGen implementations
|
||||
////
|
||||
|
||||
//
|
||||
// Original biome algorithm (Whittaker's classification + surface height)
|
||||
//
|
||||
|
||||
struct BiomeParamsOriginal : public BiomeParams {
|
||||
BiomeParamsOriginal() :
|
||||
np_heat(50, 50, v3f(750.0, 750.0, 750.0), 5349, 3, 0.5, 2.0),
|
||||
np_humidity(50, 50, v3f(750.0, 750.0, 750.0), 842, 3, 0.5, 2.0),
|
||||
np_heat_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 13, 2, 1.0, 2.0),
|
||||
np_humidity_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 90003, 2, 1.0, 2.0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void readParams(const Settings *settings);
|
||||
virtual void writeParams(Settings *settings) const;
|
||||
|
||||
NoiseParams np_heat;
|
||||
NoiseParams np_humidity;
|
||||
NoiseParams np_heat_blend;
|
||||
NoiseParams np_humidity_blend;
|
||||
};
|
||||
|
||||
class BiomeGenOriginal : public BiomeGen {
|
||||
public:
|
||||
BiomeGenOriginal(BiomeManager *biomemgr,
|
||||
BiomeParamsOriginal *params, v3s16 chunksize);
|
||||
virtual ~BiomeGenOriginal();
|
||||
|
||||
BiomeGenType getType() const { return BIOMEGEN_ORIGINAL; }
|
||||
|
||||
Biome *calcBiomeAtPoint(v3s16 pos) const;
|
||||
void calcBiomeNoise(v3s16 pmin);
|
||||
|
||||
u8 *getBiomes(s16 *heightmap);
|
||||
Biome *getBiomeAtPoint(v3s16 pos) const;
|
||||
Biome *getBiomeAtIndex(size_t index, s16 y) const;
|
||||
|
||||
Biome *calcBiomeFromNoise(float heat, float humidity, s16 y) const;
|
||||
|
||||
float *heatmap;
|
||||
float *humidmap;
|
||||
|
||||
private:
|
||||
BiomeParamsOriginal *m_params;
|
||||
|
||||
Noise *noise_heat;
|
||||
Noise *noise_humidity;
|
||||
Noise *noise_heat_blend;
|
||||
Noise *noise_humidity_blend;
|
||||
};
|
||||
|
||||
|
||||
////
|
||||
//// BiomeManager
|
||||
////
|
||||
|
||||
class BiomeManager : public ObjDefManager {
|
||||
public:
|
||||
static const char *OBJECT_TITLE;
|
||||
|
||||
BiomeManager(IGameDef *gamedef);
|
||||
virtual ~BiomeManager();
|
||||
|
||||
@ -73,15 +195,36 @@ public:
|
||||
return new Biome;
|
||||
}
|
||||
|
||||
BiomeGen *createBiomeGen(BiomeGenType type, BiomeParams *params, v3s16 chunksize)
|
||||
{
|
||||
switch (type) {
|
||||
case BIOMEGEN_ORIGINAL:
|
||||
return new BiomeGenOriginal(this,
|
||||
(BiomeParamsOriginal *)params, chunksize);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BiomeParams *createBiomeParams(BiomeGenType type)
|
||||
{
|
||||
switch (type) {
|
||||
case BIOMEGEN_ORIGINAL:
|
||||
return new BiomeParamsOriginal;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void clear();
|
||||
|
||||
void calcBiomes(s16 sx, s16 sy, float *heat_map, float *humidity_map,
|
||||
s16 *height_map, u8 *biomeid_map);
|
||||
Biome *getBiome(float heat, float humidity, s16 y);
|
||||
// Looks for pos in the biome cache, and if non-existent, looks up by noise
|
||||
u8 getBiomeAtPoint(v3s16 pos);
|
||||
|
||||
private:
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -528,24 +528,26 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
case MGOBJ_BIOMEMAP: {
|
||||
if (!mg->biomemap)
|
||||
if (!mg->biomegen)
|
||||
return 0;
|
||||
|
||||
lua_newtable(L);
|
||||
for (size_t i = 0; i != maplen; i++) {
|
||||
lua_pushinteger(L, mg->biomemap[i]);
|
||||
lua_pushinteger(L, mg->biomegen->biomemap[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
case MGOBJ_HEATMAP: {
|
||||
if (!mg->heatmap)
|
||||
if (!mg->biomegen || mg->biomegen->getType() != BIOMEGEN_ORIGINAL)
|
||||
return 0;
|
||||
|
||||
BiomeGenOriginal *bg = (BiomeGenOriginal *)mg->biomegen;
|
||||
|
||||
lua_newtable(L);
|
||||
for (size_t i = 0; i != maplen; i++) {
|
||||
lua_pushnumber(L, mg->heatmap[i]);
|
||||
lua_pushnumber(L, bg->heatmap[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
@ -553,12 +555,14 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
|
||||
}
|
||||
|
||||
case MGOBJ_HUMIDMAP: {
|
||||
if (!mg->humidmap)
|
||||
if (!mg->biomegen || mg->biomegen->getType() != BIOMEGEN_ORIGINAL)
|
||||
return 0;
|
||||
|
||||
BiomeGenOriginal *bg = (BiomeGenOriginal *)mg->biomegen;
|
||||
|
||||
lua_newtable(L);
|
||||
for (size_t i = 0; i != maplen; i++) {
|
||||
lua_pushnumber(L, mg->humidmap[i]);
|
||||
lua_pushnumber(L, bg->humidmap[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user