X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fbiome.cpp;h=dca900cbb986df0990402a77935208ffb30fae32;hb=564e11fc2f3731383cecedac8aade4dd9ecdc243;hp=180a9c4a5b414ea2bb4ea1c9b963b600ce5efacb;hpb=278d93a3eefcc4e1735cd2fee0528118c78e3526;p=minetest.git diff --git a/src/biome.cpp b/src/biome.cpp index 180a9c4a5..dca900cbb 100644 --- a/src/biome.cpp +++ b/src/biome.cpp @@ -1,6 +1,6 @@ /* -Minetest-c55 -Copyright (C) 2010-2011 kwolekr, Ryan Kwolek +Minetest +Copyright (C) 2010-2013 kwolekr, Ryan Kwolek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -21,70 +21,62 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "map.h" //for ManualMapVoxelManipulator #include "log.h" +#include "util/numeric.h" #include "main.h" - -#define BT_NONE 0 -#define BT_OCEAN 1 -#define BT_LAKE 2 -#define BT_SBEACH 3 -#define BT_GBEACH 4 -#define BT_PLAINS 5 -#define BT_HILLS 6 -#define BT_EXTREMEHILLS 7 -#define BT_MOUNTAINS 8 -#define BT_DESERT 9 -#define BT_DESERTHILLS 10 -#define BT_HELL 11 -#define BT_AETHER 12 - -#define BT_BTMASK 0x3F - -#define BTF_SNOW 0x40 -#define BTF_FOREST 0x80 - -#define BGFREQ_1 ( 0.40) -#define BGFREQ_2 (BGFREQ_1 + 0.05) -#define BGFREQ_3 (BGFREQ_2 + 0.08) -#define BGFREQ_4 (BGFREQ_3 + 0.35) -#define BGFREQ_5 (BGFREQ_4 + 0.18) -//BGFREQ_5 is not checked as an upper bound; it ought to sum up to 1.00, but it's okay if it doesn't. - - -/*float bg1_temps[] = {0.0}; -int bg1_biomes[] = {BT_OCEAN}; - -float bg2_temps[] = {10.0}; -int bg2_biomes[] = {BT_GBEACH, BT_SBEACH}; - -float bg3_temps[] = {30.0, 40.0}; -int bg3_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS}; - -float bg4_temps[] = {25.0, 30.0, 35.0, 40.0}; -int bg4_biomes[] = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESERTHILLS}; - -float bg5_temps[] = {5.0, 40.0}; -int bg5_biomes[] = {BT_LAKE, BT_PLAINS, BT_DESERT};*/ - -NoiseParams np_default = {20.0, 15.0, v3f(250., 250., 250.), 82341, 5, 0.6}; - - -BiomeDefManager::BiomeDefManager(IGameDef *gamedef) { - this->m_gamedef = gamedef; - this->ndef = gamedef->ndef(); - - //the initial biome group - bgroups.push_back(new std::vector); +#include "util/mathconstants.h" +#include "porting.h" + +NoiseParams nparams_biome_def_heat(50, 50, v3f(500.0, 500.0, 500.0), 5349, 3, 0.70); +NoiseParams nparams_biome_def_humidity(50, 50, v3f(500.0, 500.0, 500.0), 842, 3, 0.55); + + +BiomeDefManager::BiomeDefManager() { + biome_registration_finished = false; + np_heat = &nparams_biome_def_heat; + np_humidity = &nparams_biome_def_humidity; + + // Create default biome to be used in case none exist + Biome *b = new Biome; + + b->id = 0; + b->name = "Default"; + b->flags = 0; + + b->depth_top = 0; + b->depth_filler = 0; + + b->nname_top = "air"; + b->nname_filler = "air"; + b->nname_water = "mapgen_water_source"; + b->nname_dust = "air"; + b->nname_dust_water = "mapgen_water_source"; + + b->c_top = CONTENT_IGNORE; + b->c_filler = CONTENT_IGNORE; + b->c_water = CONTENT_IGNORE; + b->c_dust = CONTENT_IGNORE; + b->c_dust_water = CONTENT_IGNORE; + + b->height_min = -MAP_GENERATION_LIMIT; + b->height_max = MAP_GENERATION_LIMIT; + b->heat_point = 0.0; + b->humidity_point = 0.0; + + biomes.push_back(b); } BiomeDefManager::~BiomeDefManager() { - for (unsigned int i = 0; i != bgroups.size(); i++) - delete bgroups[i]; + //if (biomecache) + // delete[] biomecache; + + for (size_t i = 0; i != biomes.size(); i++) + delete biomes[i]; } Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) { - switch (btt) { + /*switch (btt) { case BIOME_TERRAIN_NORMAL: return new Biome; case BIOME_TERRAIN_LIQUID: @@ -92,142 +84,173 @@ Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) { case BIOME_TERRAIN_NETHER: return new BiomeHell; case BIOME_TERRAIN_AETHER: - return new BiomeAether; + return new BiomeSky; case BIOME_TERRAIN_FLAT: return new BiomeSuperflat; } - return NULL; -} - - -void BiomeDefManager::addBiomeGroup(float freq) { - int size = bgroup_freqs.size(); - float newfreq = freq; - - if (size) - newfreq += bgroup_freqs[size - 1]; - bgroup_freqs.push_back(newfreq); - bgroups.push_back(new std::vector); - - verbosestream << "BiomeDefManager: added biome group with frequency " << - newfreq << std::endl; + return NULL;*/ + return new Biome; } -void BiomeDefManager::addBiome(Biome *b) { - std::vector *bgroup; - - if ((unsigned int)b->groupid >= bgroups.size()) { - errorstream << "BiomeDefManager: attempted to add biome '" << b->name - << "' to nonexistent biome group " << b->groupid << std::endl; - return; +// just a PoC, obviously needs optimization later on (precalculate this) +void BiomeDefManager::calcBiomes(BiomeNoiseInput *input, u8 *biomeid_map) { + int i = 0; + for (int y = 0; y != input->mapsize.Y; y++) { + for (int x = 0; x != input->mapsize.X; x++, i++) { + float heat = (input->heat_map[i] + 1) * 50; + float humidity = (input->humidity_map[i] + 1) * 50; + biomeid_map[i] = getBiome(heat, humidity, input->height_map[i])->id; + } } - - bgroup = bgroups[b->groupid]; - bgroup->push_back(b); - - verbosestream << "BiomeDefManager: added biome '" << b->name << - "' to biome group " << b->groupid << std::endl; -} - - -void BiomeDefManager::addDefaultBiomes() { - Biome *b; - - b = new Biome; - b->name = "Default"; - b->n_top = MapNode(ndef->getId("mapgen_stone")); - b->n_filler = b->n_top; - b->ntopnodes = 0; - b->height_min = -MAP_GENERATION_LIMIT; - b->height_max = MAP_GENERATION_LIMIT; - b->heat_min = FLT_MIN; - b->heat_max = FLT_MAX; - b->humidity_min = FLT_MIN; - b->humidity_max = FLT_MAX; - b->np = &np_default; - biome_default = b; } -Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) { - std::vector *bgroup; +void BiomeDefManager::resolveNodeNames(INodeDefManager *ndef) { Biome *b; - int i; - - int ngroups = bgroup_freqs.size(); - if (!ngroups) - return biome_default; - for (i = 0; (i != ngroups) && (bgfreq > bgroup_freqs[i]); i++); - bgroup = bgroups[i]; - - int nbiomes = bgroup->size(); - for (i = 0; i != nbiomes; i++) { - b = bgroup->operator[](i); - if (heat >= b->heat_min && heat <= b->heat_max && - humidity >= b->humidity_min && humidity <= b->humidity_max) - return b; + + biome_registration_finished = true; + + for (size_t i = 0; i < biomes.size(); i++) { + b = biomes[i]; + + b->c_top = ndef->getId(b->nname_top); + if (b->c_top == CONTENT_IGNORE) { + errorstream << "BiomeDefManager::resolveNodeNames: node '" + << b->nname_top << "' not defined" << std::endl; + b->c_top = CONTENT_AIR; + b->depth_top = 0; + } + + b->c_filler = ndef->getId(b->nname_filler); + if (b->c_filler == CONTENT_IGNORE) { + errorstream << "BiomeDefManager::resolveNodeNames: node '" + << b->nname_filler << "' not defined" << std::endl; + b->c_filler = CONTENT_AIR; + b->depth_filler = 0; + } + + b->c_water = ndef->getId(b->nname_water); + if (b->c_water == CONTENT_IGNORE) { + errorstream << "BiomeDefManager::resolveNodeNames: node '" + << b->nname_water << "' not defined" << std::endl; + b->c_water = CONTENT_AIR; + } + + b->c_dust = ndef->getId(b->nname_dust); + if (b->c_dust == CONTENT_IGNORE) { + errorstream << "BiomeDefManager::resolveNodeNames: node '" + << b->nname_dust << "' not defined" << std::endl; + } + + b->c_dust_water = ndef->getId(b->nname_dust_water); + if (b->c_dust_water == CONTENT_IGNORE) { + errorstream << "BiomeDefManager::resolveNodeNames: node '" + << b->nname_dust_water << "' not defined" << std::endl; + } } - - return biome_default; } -//////////////////////////// [ Generic biome ] //////////////////////////////// - - -int Biome::getSurfaceHeight(float noise_terrain) { - return np->offset + np->scale * noise_terrain; -} - - -void Biome::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) { +void BiomeDefManager::addBiome(Biome *b) { + if (biome_registration_finished) { + errorstream << "BIomeDefManager: biome registration already finished, dropping " << b->name <= 0xFF) { + errorstream << "BiomeDefManager: too many biomes, dropping " << b->name << std::endl; + delete b; + return; + } + b->id = (u8)nbiomes; + biomes.push_back(b); + verbosestream << "BiomeDefManager: added biome " << b->name << std::endl; } -///////////////////////////// [ Ocean biome ] ///////////////////////////////// - +Biome *BiomeDefManager::getBiome(float heat, float humidity, s16 y) { + Biome *b, *biome_closest = NULL; + float dist_min = FLT_MAX; -void BiomeLiquid::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) { + for (size_t i = 1; i < biomes.size(); i++) { + b = biomes[i]; + if (y > b->height_max || y < b->height_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 : biomes[0]; } -///////////////////////////// [ Nether biome ] ///////////////////////////////// - - -int BiomeHell::getSurfaceHeight(float noise_terrain) { - return np->offset + np->scale * noise_terrain; +u8 BiomeDefManager::getBiomeIdByName(const char *name) { + for (size_t i = 0; i != biomes.size(); i++) { + if (!strcasecmp(name, biomes[i]->name.c_str())) + return i; + } + + return 0; } -void BiomeHell::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) { +///////////////////////////// Weather -} +s16 BiomeDefManager::calcBlockHeat(v3s16 p, u64 seed, float timeofday, float totaltime) { + //variant 1: full random + //f32 heat = NoisePerlin3D(np_heat, p.X, env->getGameTime()/100, p.Z, seed); -///////////////////////////// [ Aether biome ] //////////////////////////////// + //variant 2: season change based on default heat map + const f32 offset = 20; // = np_heat->offset + const f32 scale = 20; // = np_heat->scale + const f32 range = 20; + f32 heat = NoisePerlin2D(np_heat, p.X, p.Z, seed); // 0..50..100 + heat -= np_heat->offset; // -50..0..+50 -int BiomeAether::getSurfaceHeight(float noise_terrain) { - return np->offset + np->scale * noise_terrain; -} + // normalizing - todo REMOVE after fixed NoiseParams nparams_biome_def_heat = {50, 50, -> 20, 50, + if (np_heat->scale) + heat /= np_heat->scale / scale; // -20..0..+20 + f32 seasonv = totaltime; + seasonv /= 86400 * g_settings->getS16("year_days"); // season change speed + seasonv += (f32)p.X / 3000; // you can walk to area with other season + seasonv = sin(seasonv * M_PI); + heat += (range * (heat < 0 ? 2 : 0.5)) * seasonv; // -60..0..30 -void BiomeAether::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) { + heat += offset; // -40..0..50 + heat += p.Y / -333; // upper=colder, lower=hotter, 3c per 1000 + // daily change, hotter at sun +4, colder at night -4 + heat += 8 * (sin(cycle_shift(timeofday, -0.25) * M_PI) - 0.5); //-44..20..54 + + return heat; } -/////////////////////////// [ Superflat biome ] /////////////////////////////// - - -int BiomeSuperflat::getSurfaceHeight(float noise_terrain) { - return ntopnodes; -} +s16 BiomeDefManager::calcBlockHumidity(v3s16 p, u64 seed, float timeofday, float totaltime) { + f32 humidity = NoisePerlin2D(np_humidity, p.X, p.Z, seed); -void BiomeSuperflat::genColumn(Mapgen *mapgen, int x, int z, int y1, int y2) { + f32 seasonv = totaltime; + seasonv /= 86400 * 2; // bad weather change speed (2 days) + seasonv += (f32)p.Z / 300; + humidity += 30 * sin(seasonv * M_PI); + humidity += -12 * (sin(cycle_shift(timeofday, -0.1) * M_PI) - 0.5); + humidity = rangelim(humidity, 0, 100); + + return humidity; }