Move biome calculation to BiomeGen
authorkwolekr <kwolekr@minetest.net>
Thu, 28 Apr 2016 07:43:09 +0000 (03:43 -0400)
committerkwolekr <kwolekr@minetest.net>
Sat, 28 May 2016 03:23:58 +0000 (23:23 -0400)
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.

16 files changed:
src/emerge.cpp
src/mapgen.cpp
src/mapgen.h
src/mapgen_flat.cpp
src/mapgen_flat.h
src/mapgen_fractal.cpp
src/mapgen_fractal.h
src/mapgen_v5.cpp
src/mapgen_v5.h
src/mapgen_v7.cpp
src/mapgen_v7.h
src/mapgen_valleys.cpp
src/mapgen_valleys.h
src/mg_biome.cpp
src/mg_biome.h
src/script/lua_api/l_mapgen.cpp

index 93e8f2b30a92abcbbd81f226b75ae00e8d5bb546..a2a10a177f1caa62d77da9055306edaaa2d31ef4 100644 (file)
@@ -181,8 +181,6 @@ EmergeManager::~EmergeManager()
        delete oremgr;
        delete decomgr;
        delete schemmgr;
-
-       delete params.sparams;
 }
 
 
index b3c9380a04a41c426ca639b603e61ec3e2ce53ca..e269bf4545b88345953bebf5bdb9b5cd3a4c72fd 100644 (file)
@@ -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);
index abc3d2e899af04d3bdc8027edf9ea827014e47d9..554ec6084c74a0f7d31d028e96ccffb33754a261 100644 (file)
@@ -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();
index 4669f1716f9567576cf6cc0250b8dec584011c32..cb9aa9a8b3d9f4cc6c99af993860a8bd42c5f01c 100644 (file)
@@ -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);
index 8aed09be547ea2aa0fca0c872dd230131c93aca8..53fd66a674557809024c22351c896ada67f7e659 100644 (file)
@@ -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);
 };
index e2e29f875169023f5280901c527f3a90ac125095..9671a21438e19c25a19b93df0b6a831d11e86ab1 100644 (file)
@@ -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);
index dd96045e2f90b79cdc1ad7d3c96e349f9bb70a38..a0e51b2c62b0d11458c04df135cf4e2879a80d15 100644 (file)
@@ -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);
 };
index b98acb9287cf09137f2899ff2aeb39794d2cc941..829a1f432165a58e2aaf06791d9c2b889401a8ac 100644 (file)
@@ -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);
index fd2f7f4d88873d93f11a9cd0778f8986d8134976..eef3da617816150f3db86150363ec922bc68c80f 100644 (file)
@@ -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();
 };
index 9fb65f577e36410ecfa81e4dd5bfaace63a98255..fddb346827347c39a3dfca64d9e33895f701f73f 100644 (file)
@@ -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);
index c25220646a3ff052c9a4c1babcb4df631b10c534..a8dd9986dc04c0ec18d6db6a063aed0eadf413bf 100644 (file)
@@ -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);
index 0ec5409cb361d5e3a35d9719739a6f8ce15bd2f0..44083d9d34af7d21c93c002c7df9e818cc46bfda 100644 (file)
@@ -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
index 5224ea54be774a68bf2aba83cf850d585794e64f..0e268c1cf4e40b1c7d2bf170928de3a85ca60c05 100644 (file)
@@ -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);
index 9ab8d06cc81548c42e52c71f8b2d3f3035a8ad0d..dac0f7acc93bd400199aa01dc62eb6aa68604f8d 100644 (file)
@@ -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()
 {
index 8d519f808cc175de92254c1c2dea33a72315e397..e9378fd7926174c4ad3a59dd1fd5c0d6c8a1185e 100644 (file)
@@ -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
index fb839176b8d71d71e187897574568791f5ad87a2..405b93b86149708eef5421da776966c6c4603969 100644 (file)
@@ -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);
                }