aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkwolekr <kwolekr@minetest.net>2016-04-28 03:43:09 -0400
committerkwolekr <kwolekr@minetest.net>2016-05-27 23:23:58 -0400
commit76f485647983ebd7eb4c3abbca0869d13f76920b (patch)
tree6e6f4745311f2ac834780b5bf142dfeeea3aceb0
parentfa6b21a15b415cd82dce6896b94a5341b7dd76f0 (diff)
downloadminetest-76f485647983ebd7eb4c3abbca0869d13f76920b.tar.gz
minetest-76f485647983ebd7eb4c3abbca0869d13f76920b.tar.bz2
minetest-76f485647983ebd7eb4c3abbca0869d13f76920b.zip
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.
-rw-r--r--src/emerge.cpp2
-rw-r--r--src/mapgen.cpp38
-rw-r--r--src/mapgen.h21
-rw-r--r--src/mapgen_flat.cpp48
-rw-r--r--src/mapgen_flat.h2
-rw-r--r--src/mapgen_fractal.cpp48
-rw-r--r--src/mapgen_fractal.h7
-rw-r--r--src/mapgen_v5.cpp46
-rw-r--r--src/mapgen_v5.h7
-rw-r--r--src/mapgen_v7.cpp61
-rw-r--r--src/mapgen_v7.h8
-rw-r--r--src/mapgen_valleys.cpp70
-rw-r--r--src/mapgen_valleys.h11
-rw-r--r--src/mg_biome.cpp169
-rw-r--r--src/mg_biome.h155
-rw-r--r--src/script/lua_api/l_mapgen.cpp16
16 files changed, 413 insertions, 296 deletions
diff --git a/src/emerge.cpp b/src/emerge.cpp
index 93e8f2b30..a2a10a177 100644
--- a/src/emerge.cpp
+++ b/src/emerge.cpp
@@ -181,8 +181,6 @@ EmergeManager::~EmergeManager()
delete oremgr;
delete decomgr;
delete schemmgr;
-
- delete params.sparams;
}
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index b3c9380a0..e269bf454 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -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);
diff --git a/src/mapgen.h b/src/mapgen.h
index abc3d2e89..554ec6084 100644
--- a/src/mapgen.h
+++ b/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();
diff --git a/src/mapgen_flat.cpp b/src/mapgen_flat.cpp
index 4669f1716..cb9aa9a8b 100644
--- a/src/mapgen_flat.cpp
+++ b/src/mapgen_flat.cpp
@@ -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(&params->np_biome_heat, seed, csize.X, csize.Z);
- noise_humidity = new Noise(&params->np_biome_humidity, seed, csize.X, csize.Z);
- noise_heat_blend = new Noise(&params->np_biome_heat_blend, seed, csize.X, csize.Z);
- noise_humidity_blend = new Noise(&params->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);
diff --git a/src/mapgen_flat.h b/src/mapgen_flat.h
index 8aed09be5..53fd66a67 100644
--- a/src/mapgen_flat.h
+++ b/src/mapgen_flat.h
@@ -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);
};
diff --git a/src/mapgen_fractal.cpp b/src/mapgen_fractal.cpp
index e2e29f875..9671a2143 100644
--- a/src/mapgen_fractal.cpp
+++ b/src/mapgen_fractal.cpp
@@ -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(&params->np_biome_heat, seed, csize.X, csize.Z);
- noise_humidity = new Noise(&params->np_biome_humidity, seed, csize.X, csize.Z);
- noise_heat_blend = new Noise(&params->np_biome_heat_blend, seed, csize.X, csize.Z);
- noise_humidity_blend = new Noise(&params->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;
}
@@ -217,7 +207,7 @@ int MapgenFractal::getSpawnLevelAtPoint(v2s16 p)
s16 search_start = MYMAX(seabed_level, water_level + 1);
if (seabed_level > water_level)
solid_below = true;
-
+
for (s16 y = search_start; y <= search_start + 128; y++) {
if (getFractalAtPoint(p.X, y, p.Y)) { // Fractal node
solid_below = true;
@@ -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);
diff --git a/src/mapgen_fractal.h b/src/mapgen_fractal.h
index dd96045e2..a0e51b2c6 100644
--- a/src/mapgen_fractal.h
+++ b/src/mapgen_fractal.h
@@ -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);
};
diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp
index b98acb928..829a1f432 100644
--- a/src/mapgen_v5.cpp
+++ b/src/mapgen_v5.cpp
@@ -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(&params->np_biome_heat, seed, csize.X, csize.Z);
- noise_humidity = new Noise(&params->np_biome_humidity, seed, csize.X, csize.Z);
- noise_heat_blend = new Noise(&params->np_biome_heat_blend, seed, csize.X, csize.Z);
- noise_humidity_blend = new Noise(&params->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);
diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h
index fd2f7f4d8..eef3da617 100644
--- a/src/mapgen_v5.h
+++ b/src/mapgen_v5.h
@@ -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();
};
diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp
index 9fb65f577..fddb34682 100644
--- a/src/mapgen_v7.cpp
+++ b/src/mapgen_v7.cpp
@@ -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(&params->np_biome_heat, seed, csize.X, csize.Z);
- noise_humidity = new Noise(&params->np_biome_humidity, seed, csize.X, csize.Z);
- noise_heat_blend = new Noise(&params->np_biome_heat_blend, seed, csize.X, csize.Z);
- noise_humidity_blend = new Noise(&params->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);
diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h
index c25220646..a8dd9986d 100644
--- a/src/mapgen_v7.h
+++ b/src/mapgen_v7.h
@@ -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);
diff --git a/src/mapgen_valleys.cpp b/src/mapgen_valleys.cpp
index 0ec5409cb..44083d9d3 100644
--- a/src/mapgen_valleys.cpp
+++ b/src/mapgen_valleys.cpp
@@ -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(&params->np_biome_heat_blend, seed, csize.X, csize.Z);
- noise_heat = new Noise(&params->np_biome_heat, seed, csize.X, csize.Z);
- noise_humidity_blend = new Noise(&params->np_biome_humidity_blend, seed, csize.X, csize.Z);
- noise_humidity = new Noise(&params->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
diff --git a/src/mapgen_valleys.h b/src/mapgen_valleys.h
index 5224ea54b..0e268c1cf 100644
--- a/src/mapgen_valleys.h
+++ b/src/mapgen_valleys.h
@@ -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);
diff --git a/src/mg_biome.cpp b/src/mg_biome.cpp
index 9ab8d06cc..dac0f7acc 100644
--- a/src/mg_biome.cpp
+++ b/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,33 +64,152 @@ BiomeManager::BiomeManager(IGameDef *gamedef) :
}
-
BiomeManager::~BiomeManager()
{
- //if (biomecache)
- // delete[] biomecache;
}
+void BiomeManager::clear()
+{
+ EmergeManager *emerge = m_gamedef->getEmergeManager();
+
+ // Remove all dangling references in Decorations
+ DecorationManager *decomgr = emerge->decomgr;
+ for (size_t i = 0; i != decomgr->getNumObjects(); i++) {
+ Decoration *deco = (Decoration *)decomgr->getRaw(i);
+ deco->biomes.clear();
+ }
+
+ // Don't delete the first biome
+ 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);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
-// 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)
+BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr,
+ BiomeParamsOriginal *params, v3s16 chunksize)
{
- 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;
+ m_bmgr = biomemgr;
+ m_params = params;
+ m_csize = chunksize;
+
+ noise_heat = new Noise(&params->np_heat,
+ params->seed, m_csize.X, m_csize.Z);
+ noise_humidity = new Noise(&params->np_humidity,
+ params->seed, m_csize.X, m_csize.Z);
+ noise_heat_blend = new Noise(&params->np_heat_blend,
+ params->seed, m_csize.X, m_csize.Z);
+ noise_humidity_blend = new Noise(&params->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 *BiomeManager::getBiome(float heat, float humidity, s16 y)
+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_objects.size(); i++) {
- b = (Biome *)m_objects[i];
+ 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;
@@ -103,32 +223,11 @@ Biome *BiomeManager::getBiome(float heat, float humidity, s16 y)
}
}
- return biome_closest ? biome_closest : (Biome *)m_objects[0];
+ return biome_closest ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE);
}
-void BiomeManager::clear()
-{
- EmergeManager *emerge = m_gamedef->getEmergeManager();
-
- // Remove all dangling references in Decorations
- DecorationManager *decomgr = emerge->decomgr;
- for (size_t i = 0; i != decomgr->getNumObjects(); i++) {
- Decoration *deco = (Decoration *)decomgr->getRaw(i);
- deco->biomes.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;
- }
-
- m_objects.resize(1);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
void Biome::resolveNodeNames()
{
diff --git a/src/mg_biome.h b/src/mg_biome.h
index 8d519f808..e9378fd79 100644
--- a/src/mg_biome.h
+++ b/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();
};
-class BiomeManager : public ObjDefManager {
+
+////
+//// 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:
- static const char *OBJECT_TITLE;
+ 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:
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
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index fb839176b..405b93b86 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -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);
}