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.master
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;
|
||||
this->heightmap = new s16[csize.X * csize.Z];
|
||||
|
||||
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);
|
||||
|
|
|
@ -68,7 +68,7 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *
|
|||
: Mapgen(mapgenid, params, emerge)
|
||||
{
|
||||
this->m_emerge = emerge;
|
||||
this->bmgr = emerge->biomemgr;
|
||||
this->bmgr = emerge->biomemgr;
|
||||
|
||||
//// amount of elements to skip for the next index
|
||||
//// for noise/height/biome maps (not vmanip)
|
||||
|
@ -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;
|
||||
|
@ -739,9 +729,9 @@ MgStoneType MapgenValleys::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 || c == c_river_water_source)
|
||||
&& (air_above || !biome))) {
|
||||
&& (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