From 76f485647983ebd7eb4c3abbca0869d13f76920b Mon Sep 17 00:00:00 2001 From: kwolekr Date: Thu, 28 Apr 2016 03:43:09 -0400 Subject: [PATCH] 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. --- src/emerge.cpp | 2 - src/mapgen.cpp | 38 ++++--- src/mapgen.h | 21 ++-- src/mapgen_flat.cpp | 48 +++------ src/mapgen_flat.h | 2 +- src/mapgen_fractal.cpp | 48 +++------ src/mapgen_fractal.h | 7 +- src/mapgen_v5.cpp | 46 +++----- src/mapgen_v5.h | 7 +- src/mapgen_v7.cpp | 61 +++-------- src/mapgen_v7.h | 8 +- src/mapgen_valleys.cpp | 70 ++++++------ src/mapgen_valleys.h | 11 +- src/mg_biome.cpp | 185 ++++++++++++++++++++++++-------- src/mg_biome.h | 155 ++++++++++++++++++++++++-- src/script/lua_api/l_mapgen.cpp | 16 +-- 16 files changed, 421 insertions(+), 304 deletions(-) diff --git a/src/emerge.cpp b/src/emerge.cpp index 93e8f2b3..a2a10a17 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 b3c9380a..e269bf45 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 abc3d2e8..554ec608 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 @@ class Mapgen { 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 4669f171..cb9aa9a8 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(¶ms->np_biome_heat, seed, csize.X, csize.Z); - noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z); - noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z); - noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z); + //// Initialize biome generator + biomegen = emerge->biomemgr->createBiomeGen( + BIOMEGEN_ORIGINAL, params->bparams, csize); + biomemap = biomegen->biomemap; //// Resolve nodes to be used - INodeDefManager *ndef = emerge->ndef; - c_stone = ndef->getId("mapgen_stone"); c_water_source = ndef->getId("mapgen_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); @@ -128,13 +122,9 @@ MapgenFlat::~MapgenFlat() delete noise_cave1; delete noise_cave2; - delete noise_heat; - delete noise_humidity; - delete noise_heat_blend; - delete noise_humidity_blend; + delete biomegen; delete[] heightmap; - delete[] biomemap; } @@ -252,12 +242,10 @@ void MapgenFlat::makeChunk(BlockMakeData *data) // Create heightmap updateHeightmap(node_min, node_max); - // Create biomemap at heightmap surface - bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, - noise_humidity->result, heightmap, biomemap); - - // Actually place the biome-specific nodes - MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result); + // Init biome generator, place biome-specific nodes, and build biomemap + biomegen->calcBiomeNoise(node_min); + biomegen->getBiomes(heightmap); + MgStoneType stone_type = generateBiomes(); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); @@ -343,18 +331,7 @@ void MapgenFlat::calculateNoise() // only if solid terrain is present in mapchunk noise_filler_depth->perlinMap2D(x, z); - noise_heat->perlinMap2D(x, z); - noise_humidity->perlinMap2D(x, z); - noise_heat_blend->perlinMap2D(x, z); - noise_humidity_blend->perlinMap2D(x, z); - for (s32 i = 0; i < csize.X * csize.Z; i++) { - noise_heat->result[i] += noise_heat_blend->result[i]; - noise_humidity->result[i] += noise_humidity_blend->result[i]; - } - - heatmap = noise_heat->result; - humidmap = noise_humidity->result; //printf("calculateNoise: %dus\n", t.stop()); } @@ -406,7 +383,7 @@ s16 MapgenFlat::generateTerrain() } -MgStoneType MapgenFlat::generateBiomes(float *heat_map, float *humidity_map) +MgStoneType MapgenFlat::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; @@ -443,7 +420,8 @@ MgStoneType MapgenFlat::generateBiomes(float *heat_map, float *humidity_map) // 3. When stone or water is detected but biome has not yet been calculated. if ((c == c_stone && (air_above || water_above || !biome)) || (c == c_water_source && (air_above || !biome))) { - biome = bmgr->getBiome(heat_map[index], humidity_map[index], y); + biome = biomegen->getBiomeAtIndex(index, y); + depth_top = biome->depth_top; base_filler = MYMAX(depth_top + biome->depth_filler + noise_filler_depth->result[index], 0); diff --git a/src/mapgen_flat.h b/src/mapgen_flat.h index 8aed09be..53fd66a6 100644 --- a/src/mapgen_flat.h +++ b/src/mapgen_flat.h @@ -104,7 +104,7 @@ class MapgenFlat : public Mapgen { 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 e2e29f87..9671a214 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(¶ms->np_biome_heat, seed, csize.X, csize.Z); - noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z); - noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z); - noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z); + //// Initialize biome generator + biomegen = emerge->biomemgr->createBiomeGen( + BIOMEGEN_ORIGINAL, params->bparams, csize); + biomemap = biomegen->biomemap; this->formula = fractal / 2 + fractal % 2; this->julia = fractal % 2 == 0; //// Resolve nodes to be used - INodeDefManager *ndef = emerge->ndef; - c_stone = ndef->getId("mapgen_stone"); c_water_source = ndef->getId("mapgen_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); @@ -132,13 +126,9 @@ MapgenFractal::~MapgenFractal() delete noise_cave1; delete noise_cave2; - delete noise_heat; - delete noise_humidity; - delete noise_heat_blend; - delete noise_humidity_blend; + delete biomegen; delete[] heightmap; - delete[] biomemap; } @@ -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 dd96045e..a0e51b2c 100644 --- a/src/mapgen_fractal.h +++ b/src/mapgen_fractal.h @@ -88,11 +88,6 @@ class MapgenFractal : public Mapgen { 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 @@ class MapgenFractal : public Mapgen { 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 b98acb92..829a1f43 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(¶ms->np_biome_heat, seed, csize.X, csize.Z); - noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z); - noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z); - noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z); + //// Initialize biome generator + biomegen = emerge->biomemgr->createBiomeGen( + BIOMEGEN_ORIGINAL, params->bparams, csize); + biomemap = biomegen->biomemap; //// Resolve nodes to be used - INodeDefManager *ndef = emerge->ndef; - c_stone = ndef->getId("mapgen_stone"); c_water_source = ndef->getId("mapgen_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); @@ -123,13 +117,9 @@ MapgenV5::~MapgenV5() delete noise_cave2; delete noise_ground; - delete noise_heat; - delete noise_humidity; - delete noise_heat_blend; - delete noise_humidity_blend; + delete biomegen; delete[] heightmap; - delete[] biomemap; } @@ -248,12 +238,10 @@ void MapgenV5::makeChunk(BlockMakeData *data) // Create heightmap updateHeightmap(node_min, node_max); - // Create biomemap at heightmap surface - bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, - noise_humidity->result, heightmap, biomemap); - - // Actually place the biome-specific nodes - MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result); + // Init biome generator, place biome-specific nodes, and build biomemap + biomegen->calcBiomeNoise(node_min); + biomegen->getBiomes(heightmap); + MgStoneType stone_type = generateBiomes(); // Generate caves if ((flags & MG_CAVES) && (stone_surface_max_y >= node_min.Y)) @@ -343,18 +331,7 @@ void MapgenV5::calculateNoise() // only if solid terrain is present in mapchunk noise_filler_depth->perlinMap2D(x, z); - noise_heat->perlinMap2D(x, z); - noise_humidity->perlinMap2D(x, z); - noise_heat_blend->perlinMap2D(x, z); - noise_humidity_blend->perlinMap2D(x, z); - for (s32 i = 0; i < csize.X * csize.Z; i++) { - noise_heat->result[i] += noise_heat_blend->result[i]; - noise_humidity->result[i] += noise_humidity_blend->result[i]; - } - - heatmap = noise_heat->result; - humidmap = noise_humidity->result; //printf("calculateNoise: %dus\n", t.stop()); } @@ -416,7 +393,7 @@ int MapgenV5::generateBaseTerrain() } -MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map) +MgStoneType MapgenV5::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; @@ -452,7 +429,8 @@ MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map) // 3. When stone or water is detected but biome has not yet been calculated. if ((c == c_stone && (air_above || water_above || !biome)) || (c == c_water_source && (air_above || !biome))) { - biome = bmgr->getBiome(heat_map[index], humidity_map[index], y); + biome = biomegen->getBiomeAtIndex(index, y); + depth_top = biome->depth_top; base_filler = MYMAX(depth_top + biome->depth_filler + noise_filler_depth->result[index], 0); diff --git a/src/mapgen_v5.h b/src/mapgen_v5.h index fd2f7f4d..eef3da61 100644 --- a/src/mapgen_v5.h +++ b/src/mapgen_v5.h @@ -70,11 +70,6 @@ class MapgenV5 : public Mapgen { 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 @@ class MapgenV5 : public Mapgen { 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 9fb65f57..fddb3468 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(¶ms->np_biome_heat, seed, csize.X, csize.Z); - noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z); - noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z); - noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z); + // TODO(hmmmm): should we have a way to disable biomemanager biomes? + //// Initialize biome generator + biomegen = emerge->biomemgr->createBiomeGen( + BIOMEGEN_ORIGINAL, params->bparams, csize); + biomemap = biomegen->biomemap; //// Resolve nodes to be used - INodeDefManager *ndef = emerge->ndef; - c_stone = ndef->getId("mapgen_stone"); c_water_source = ndef->getId("mapgen_water_source"); c_lava_source = ndef->getId("mapgen_lava_source"); @@ -141,14 +136,10 @@ MapgenV7::~MapgenV7() delete noise_cave1; delete noise_cave2; - delete noise_heat; - delete noise_humidity; - delete noise_heat_blend; - delete noise_humidity_blend; + delete biomegen; delete[] ridge_heightmap; delete[] heightmap; - delete[] biomemap; } @@ -279,12 +270,10 @@ void MapgenV7::makeChunk(BlockMakeData *data) // Update heightmap to include mountain terrain updateHeightmap(node_min, node_max); - // Create biomemap at heightmap surface - bmgr->calcBiomes(csize.X, csize.Z, noise_heat->result, - noise_humidity->result, heightmap, biomemap); - - // Actually place the biome-specific nodes - MgStoneType stone_type = generateBiomes(noise_heat->result, noise_humidity->result); + // Init biome generator, place biome-specific nodes, and build biomemap + biomegen->calcBiomeNoise(node_min); + biomegen->getBiomes(heightmap); + MgStoneType stone_type = generateBiomes(); if (flags & MG_CAVES) generateCaves(stone_surface_max_y); @@ -384,35 +373,10 @@ void MapgenV7::calculateNoise() // Cave noises are calculated in generateCaves() // only if solid terrain is present in mapchunk - noise_filler_depth->perlinMap2D(x, z); - noise_heat->perlinMap2D(x, z); - noise_humidity->perlinMap2D(x, z); - noise_heat_blend->perlinMap2D(x, z); - noise_humidity_blend->perlinMap2D(x, z); - - for (s32 i = 0; i < csize.X * csize.Z; i++) { - noise_heat->result[i] += noise_heat_blend->result[i]; - noise_humidity->result[i] += noise_humidity_blend->result[i]; - } - - heatmap = noise_heat->result; - humidmap = noise_humidity->result; //printf("calculateNoise: %dus\n", t.stop()); } -Biome *MapgenV7::getBiomeAtPoint(v3s16 p) -{ - float heat = NoisePerlin2D(&noise_heat->np, p.X, p.Z, seed) + - NoisePerlin2D(&noise_heat_blend->np, p.X, p.Z, seed); - float humidity = NoisePerlin2D(&noise_humidity->np, p.X, p.Z, seed) + - NoisePerlin2D(&noise_humidity_blend->np, p.X, p.Z, seed); - s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Z); - - return bmgr->getBiome(heat, humidity, groundlevel); -} - - float MapgenV7::baseTerrainLevelAtPoint(s16 x, s16 z) { float hselect = NoisePerlin2D(&noise_height_select->np, x, z, seed); @@ -553,7 +517,7 @@ void MapgenV7::generateRidgeTerrain() } -MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map) +MgStoneType MapgenV7::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; @@ -589,7 +553,8 @@ MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map) // 3. When stone or water is detected but biome has not yet been calculated. if ((c == c_stone && (air_above || water_above || !biome)) || (c == c_water_source && (air_above || !biome))) { - biome = bmgr->getBiome(heat_map[index], humidity_map[index], y); + biome = biomegen->getBiomeAtIndex(index, y); + depth_top = biome->depth_top; base_filler = MYMAX(depth_top + biome->depth_filler + noise_filler_depth->result[index], 0); diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index c2522064..a8dd9986 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -84,11 +84,6 @@ class MapgenV7 : public Mapgen { 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 @@ class MapgenV7 : public Mapgen { 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 @@ class MapgenV7 : public Mapgen { 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 0ec5409c..44083d9d 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(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z); - noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z); - noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z); - noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z); + //// Initialize biome generator + // NOTE: valleys mapgen can only use BiomeGenOriginal + biomegen = emerge->biomemgr->createBiomeGen( + BIOMEGEN_ORIGINAL, params->bparams, csize); + biomemap = biomegen->biomemap; + m_bgen = (BiomeGenOriginal *)biomegen; this->humid_rivers = (spflags & MGVALLEYS_HUMID_RIVERS); this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL); - this->humidity_adjust = params->np_biome_humidity.offset - 50.f; + this->humidity_adjust = bp->np_humidity.offset - 50.f; // a small chance of overflows if the settings are very high this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50; @@ -130,8 +129,6 @@ MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager * tcave_cache = new float[csize.Y + 2]; //// Resolve nodes to be used - INodeDefManager *ndef = emerge->ndef; - c_cobble = ndef->getId("mapgen_cobble"); c_desert_stone = ndef->getId("mapgen_desert_stone"); c_dirt = ndef->getId("mapgen_dirt"); @@ -174,12 +171,8 @@ MapgenValleys::~MapgenValleys() delete noise_valley_depth; delete noise_valley_profile; - delete noise_heat; - delete noise_heat_blend; - delete noise_humidity; - delete noise_humidity_blend; + delete biomegen; - delete[] biomemap; delete[] heightmap; delete[] tcave_cache; } @@ -293,14 +286,19 @@ void MapgenValleys::makeChunk(BlockMakeData *data) // Generate noise maps and base terrain height. calculateNoise(); + // Generate biome noises. Note this must be executed strictly before + // generateTerrain, because generateTerrain depends on intermediate + // biome-related noises. + biomegen->calcBiomeNoise(node_min); + // Generate base terrain with initial heightmaps s16 stone_surface_max_y = generateTerrain(); - // Create biomemap at heightmap surface - bmgr->calcBiomes(csize.X, csize.Z, heatmap, humidmap, heightmap, biomemap); + // Build biomemap + biomegen->getBiomes(heightmap); - // Actually place the biome-specific nodes - MgStoneType stone_type = generateBiomes(heatmap, humidmap); + // Place biome-specific nodes + MgStoneType stone_type = generateBiomes(); // Cave creation. if (flags & MG_CAVES) @@ -391,10 +389,6 @@ void MapgenValleys::calculateNoise() //TimeTaker tcn("actualNoise"); noise_filler_depth->perlinMap2D(x, z); - noise_heat_blend->perlinMap2D(x, z); - noise_heat->perlinMap2D(x, z); - noise_humidity_blend->perlinMap2D(x, z); - noise_humidity->perlinMap2D(x, z); noise_inter_valley_slope->perlinMap2D(x, z); noise_rivers->perlinMap2D(x, z); noise_terrain_height->perlinMap2D(x, z); @@ -418,9 +412,8 @@ void MapgenValleys::calculateNoise() } for (s32 index = 0; index < csize.X * csize.Z; index++) { - noise_heat->result[index] += noise_heat_blend->result[index] + heat_offset; - noise_humidity->result[index] *= humidity_scale; - noise_humidity->result[index] += noise_humidity_blend->result[index]; + m_bgen->heatmap[index] += heat_offset; + m_bgen->humidmap[index] *= humidity_scale; } TerrainNoise tn; @@ -450,9 +443,6 @@ void MapgenValleys::calculateNoise() float mount = terrainLevelFromNoise(&tn); noise_terrain_height->result[index] = mount; } - - heatmap = noise_heat->result; - humidmap = noise_humidity->result; } @@ -596,7 +586,7 @@ int MapgenValleys::generateTerrain() float river_y = noise_rivers->result[index_2d]; float surface_y = noise_terrain_height->result[index_2d]; float slope = noise_inter_valley_slope->result[index_2d]; - float t_heat = noise_heat->result[index_2d]; + float t_heat = m_bgen->heatmap[index_2d]; heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT; @@ -610,7 +600,7 @@ int MapgenValleys::generateTerrain() t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill; // If humidity is low or heat is high, lower the water table. - float delta = noise_humidity->result[index_2d] - 50.f; + float delta = m_bgen->humidmap[index_2d] - 50.f; if (delta < 0.f) { float t_evap = (t_heat - 32.f) / evaporation; river_y += delta * MYMAX(t_evap, 0.08f); @@ -672,7 +662,7 @@ int MapgenValleys::generateTerrain() // Use base ground (water table) in a riverbed, to // avoid an unnatural rise in humidity. float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]); - float humid = noise_humidity->result[index_2d]; + float humid = m_bgen->humidmap[index_2d]; float water_depth = (t_alt - river_y) / humidity_dropoff; humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f)); @@ -683,7 +673,7 @@ int MapgenValleys::generateTerrain() if (t_alt > 0.f) humid -= alt_to_humid * t_alt / altitude_chill; - noise_humidity->result[index_2d] = humid; + m_bgen->humidmap[index_2d] = humid; } // Assign the heat adjusted by any changed altitudes. @@ -693,9 +683,9 @@ int MapgenValleys::generateTerrain() float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]); if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y)) // The altitude hasn't changed. Use the first result. - noise_heat->result[index_2d] = t_heat; + m_bgen->heatmap[index_2d] = t_heat; else if (t_alt > 0.f) - noise_heat->result[index_2d] -= alt_to_heat * t_alt / altitude_chill; + m_bgen->heatmap[index_2d] -= alt_to_heat * t_alt / altitude_chill; } } @@ -703,7 +693,7 @@ int MapgenValleys::generateTerrain() } -MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map) +MgStoneType MapgenValleys::generateBiomes() { v3s16 em = vm->m_area.getExtent(); u32 index = 0; @@ -739,9 +729,9 @@ MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map) // 3. When stone or water is detected but biome has not yet been calculated. if ((c == c_stone && (air_above || water_above || !biome)) || ((c == c_water_source || c == c_river_water_source) - && (air_above || !biome))) { + && (air_above || !biome))) { // Both heat and humidity have already been adjusted for altitude. - biome = bmgr->getBiome(heat_map[index], humidity_map[index], y); + biome = biomegen->getBiomeAtIndex(index, y); depth_top = biome->depth_top; base_filler = MYMAX(depth_top diff --git a/src/mapgen_valleys.h b/src/mapgen_valleys.h index 5224ea54..0e268c1c 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 @@ class MapgenValleys : public Mapgen { private: EmergeManager *m_emerge; BiomeManager *bmgr; + BiomeGenOriginal *m_bgen; int ystride; int zstride; @@ -136,11 +138,6 @@ class MapgenValleys : public Mapgen { 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 @@ class MapgenValleys : public Mapgen { 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 9ab8d06c..dac0f7ac 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,49 +64,11 @@ BiomeManager::BiomeManager(IGameDef *gamedef) : } - BiomeManager::~BiomeManager() { - //if (biomecache) - // delete[] biomecache; } - -// just a PoC, obviously needs optimization later on (precalculate this) -void BiomeManager::calcBiomes(s16 sx, s16 sy, float *heat_map, - float *humidity_map, s16 *height_map, u8 *biomeid_map) -{ - for (s32 i = 0; i != sx * sy; i++) { - Biome *biome = getBiome(heat_map[i], humidity_map[i], height_map[i]); - biomeid_map[i] = biome->index; - } -} - - -Biome *BiomeManager::getBiome(float heat, float humidity, s16 y) -{ - Biome *b, *biome_closest = NULL; - float dist_min = FLT_MAX; - - for (size_t i = 1; i < m_objects.size(); i++) { - b = (Biome *)m_objects[i]; - if (!b || y > b->y_max || y < b->y_min) - continue; - - float d_heat = heat - b->heat_point; - float d_humidity = humidity - b->humidity_point; - float dist = (d_heat * d_heat) + - (d_humidity * d_humidity); - if (dist < dist_min) { - dist_min = dist; - biome_closest = b; - } - } - - return biome_closest ? biome_closest : (Biome *)m_objects[0]; -} - void BiomeManager::clear() { EmergeManager *emerge = m_gamedef->getEmergeManager(); @@ -118,17 +81,153 @@ void BiomeManager::clear() } // Don't delete the first biome - for (size_t i = 1; i < m_objects.size(); i++) { - Biome *b = (Biome *)m_objects[i]; - delete b; - } + for (size_t i = 1; i < m_objects.size(); i++) + delete (Biome *)m_objects[i]; m_objects.resize(1); } +//////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// +void BiomeParamsOriginal::readParams(const Settings *settings) +{ + settings->getNoiseParams("mg_biome_np_heat", np_heat); + settings->getNoiseParams("mg_biome_np_heat_blend", np_heat_blend); + settings->getNoiseParams("mg_biome_np_humidity", np_humidity); + settings->getNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend); +} + + +void BiomeParamsOriginal::writeParams(Settings *settings) const +{ + settings->setNoiseParams("mg_biome_np_heat", np_heat); + settings->setNoiseParams("mg_biome_np_heat_blend", np_heat_blend); + settings->setNoiseParams("mg_biome_np_humidity", np_humidity); + settings->setNoiseParams("mg_biome_np_humidity_blend", np_humidity_blend); +} + + +//////////////////////////////////////////////////////////////////////////////// + +BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr, + BiomeParamsOriginal *params, v3s16 chunksize) +{ + m_bmgr = biomemgr; + m_params = params; + m_csize = chunksize; + + noise_heat = new Noise(¶ms->np_heat, + params->seed, m_csize.X, m_csize.Z); + noise_humidity = new Noise(¶ms->np_humidity, + params->seed, m_csize.X, m_csize.Z); + noise_heat_blend = new Noise(¶ms->np_heat_blend, + params->seed, m_csize.X, m_csize.Z); + noise_humidity_blend = new Noise(¶ms->np_humidity_blend, + params->seed, m_csize.X, m_csize.Z); + + heatmap = noise_heat->result; + humidmap = noise_humidity->result; + biomemap = new u8[m_csize.X * m_csize.Z]; +} + +BiomeGenOriginal::~BiomeGenOriginal() +{ + delete []biomemap; + + delete noise_heat; + delete noise_humidity; + delete noise_heat_blend; + delete noise_humidity_blend; +} + + +Biome *BiomeGenOriginal::calcBiomeAtPoint(v3s16 pos) const +{ + float heat = + NoisePerlin2D(&m_params->np_heat, pos.X, pos.Z, m_params->seed) + + NoisePerlin2D(&m_params->np_heat_blend, pos.X, pos.Z, m_params->seed); + float humidity = + NoisePerlin2D(&m_params->np_humidity, pos.X, pos.Z, m_params->seed) + + NoisePerlin2D(&m_params->np_humidity_blend, pos.X, pos.Z, m_params->seed); + + return calcBiomeFromNoise(heat, humidity, pos.Y); +} + + +void BiomeGenOriginal::calcBiomeNoise(v3s16 pmin) +{ + m_pmin = pmin; + + noise_heat->perlinMap2D(pmin.X, pmin.Z); + noise_humidity->perlinMap2D(pmin.X, pmin.Z); + noise_heat_blend->perlinMap2D(pmin.X, pmin.Z); + noise_humidity_blend->perlinMap2D(pmin.X, pmin.Z); + + for (s32 i = 0; i < m_csize.X * m_csize.Z; i++) { + noise_heat->result[i] += noise_heat_blend->result[i]; + noise_humidity->result[i] += noise_humidity_blend->result[i]; + } +} + + +u8 *BiomeGenOriginal::getBiomes(s16 *heightmap) +{ + for (s32 i = 0; i != m_csize.X * m_csize.Z; i++) { + Biome *biome = calcBiomeFromNoise( + noise_heat->result[i], + noise_humidity->result[i], + heightmap[i]); + + biomemap[i] = biome->index; + } + + return biomemap; +} + + +Biome *BiomeGenOriginal::getBiomeAtPoint(v3s16 pos) const +{ + return getBiomeAtIndex( + (pos.Z - m_pmin.Z) * m_csize.X + (pos.X - m_pmin.X), + pos.Y); +} + + +Biome *BiomeGenOriginal::getBiomeAtIndex(size_t index, s16 y) const +{ + return calcBiomeFromNoise( + noise_heat->result[index], + noise_humidity->result[index], + y); +} + + +Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, s16 y) const +{ + Biome *b, *biome_closest = NULL; + float dist_min = FLT_MAX; + + for (size_t i = 1; i < m_bmgr->getNumObjects(); i++) { + b = (Biome *)m_bmgr->getRaw(i); + if (!b || y > b->y_max || y < b->y_min) + continue; + + float d_heat = heat - b->heat_point; + float d_humidity = humidity - b->humidity_point; + float dist = (d_heat * d_heat) + + (d_humidity * d_humidity); + if (dist < dist_min) { + dist_min = dist; + biome_closest = b; + } + } + + return biome_closest ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE); +} + + +//////////////////////////////////////////////////////////////////////////////// void Biome::resolveNodeNames() { diff --git a/src/mg_biome.h b/src/mg_biome.h index 8d519f80..e9378fd7 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 @@ class Biome : public ObjDef, public NodeResolver { virtual void resolveNodeNames(); }; + +//// +//// BiomeGen +//// + +enum BiomeGenType { + BIOMEGEN_ORIGINAL, +}; + +struct BiomeParams { + virtual void readParams(const Settings *settings) = 0; + virtual void writeParams(Settings *settings) const = 0; + virtual ~BiomeParams() {} + + int seed; +}; + +class BiomeGen { +public: + virtual ~BiomeGen() {} + virtual BiomeGenType getType() const = 0; + + // Calculates the biome at the exact position provided. This function can + // be called at any time, but may be less efficient than the latter methods, + // depending on implementation. + virtual Biome *calcBiomeAtPoint(v3s16 pos) const = 0; + + // Computes any intermediate results needed for biome generation. Must be + // called before using any of: getBiomes, getBiomeAtPoint, or getBiomeAtIndex. + // Calling this invalidates the previous results stored in biomemap. + virtual void calcBiomeNoise(v3s16 pmin) = 0; + + // Gets all biomes in current chunk using each corresponding element of + // heightmap as the y position, then stores the results by biome index in + // biomemap (also returned) + virtual u8 *getBiomes(s16 *heightmap) = 0; + + // Gets a single biome at the specified position, which must be contained + // in the region formed by m_pmin and (m_pmin + m_csize - 1). + virtual Biome *getBiomeAtPoint(v3s16 pos) const = 0; + + // Same as above, but uses a raw numeric index correlating to the (x,z) position. + virtual Biome *getBiomeAtIndex(size_t index, s16 y) const = 0; + + // Result of calcBiomes bulk computation. + u8 *biomemap; + +protected: + BiomeManager *m_bmgr; + v3s16 m_pmin; + v3s16 m_csize; +}; + + +//// +//// BiomeGen implementations +//// + +// +// Original biome algorithm (Whittaker's classification + surface height) +// + +struct BiomeParamsOriginal : public BiomeParams { + BiomeParamsOriginal() : + np_heat(50, 50, v3f(750.0, 750.0, 750.0), 5349, 3, 0.5, 2.0), + np_humidity(50, 50, v3f(750.0, 750.0, 750.0), 842, 3, 0.5, 2.0), + np_heat_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 13, 2, 1.0, 2.0), + np_humidity_blend(0, 1.5, v3f(8.0, 8.0, 8.0), 90003, 2, 1.0, 2.0) + { + } + + virtual void readParams(const Settings *settings); + virtual void writeParams(Settings *settings) const; + + NoiseParams np_heat; + NoiseParams np_humidity; + NoiseParams np_heat_blend; + NoiseParams np_humidity_blend; +}; + +class BiomeGenOriginal : public BiomeGen { +public: + BiomeGenOriginal(BiomeManager *biomemgr, + BiomeParamsOriginal *params, v3s16 chunksize); + virtual ~BiomeGenOriginal(); + + BiomeGenType getType() const { return BIOMEGEN_ORIGINAL; } + + Biome *calcBiomeAtPoint(v3s16 pos) const; + void calcBiomeNoise(v3s16 pmin); + + u8 *getBiomes(s16 *heightmap); + Biome *getBiomeAtPoint(v3s16 pos) const; + Biome *getBiomeAtIndex(size_t index, s16 y) const; + + Biome *calcBiomeFromNoise(float heat, float humidity, s16 y) const; + + float *heatmap; + float *humidmap; + +private: + BiomeParamsOriginal *m_params; + + Noise *noise_heat; + Noise *noise_humidity; + Noise *noise_heat_blend; + Noise *noise_humidity_blend; +}; + + +//// +//// BiomeManager +//// + class BiomeManager : public ObjDefManager { public: - static const char *OBJECT_TITLE; - BiomeManager(IGameDef *gamedef); virtual ~BiomeManager(); @@ -73,15 +195,36 @@ class BiomeManager : public ObjDefManager { 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 fb839176..405b93b8 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); }