diff --git a/res/generators/default.lua b/res/generators/default.lua index e96ea22e..10f3b08c 100644 --- a/res/generators/default.lua +++ b/res/generators/default.lua @@ -99,14 +99,27 @@ function generate_heightmap(x, y, w, h, seed) return map end -function generate_biome_parameters(x, y, w, h, seed) +local function _generate_biome_parameters(x, y, w, h, seed, s) local tempmap = Heightmap(w, h) tempmap.noiseSeed = seed + 5324 - tempmap:noise({x, y}, 0.4, 4) + tempmap:noise({x, y}, 0.4*s, 4) local hummap = Heightmap(w, h) hummap.noiseSeed = seed + 953 - hummap:noise({x, y}, 0.16, 4) + hummap:noise({x, y}, 0.16*s, 4) tempmap:pow(2) hummap:pow(2) return tempmap, hummap end + +function generate_biome_parameters(x, y, w, h, seed) + local bpd = 4 + local tmap, hmap = _generate_biome_parameters( + math.floor(x/bpd), math.floor(y/bpd), + math.floor(w/bpd)+1, math.floor(h/bpd)+1, seed, bpd) + tmap:resize(w+bpd, h+bpd, 'linear') + tmap:crop(0, 0, w, h) + + hmap:resize(w+bpd, h+bpd, 'linear') + hmap:crop(0, 0, w, h) + return tmap, hmap +end diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index 226acd48..b1db58fe 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -35,7 +35,11 @@ ChunksController::ChunksController(Level* level, uint padding) ChunksController::~ChunksController() = default; -void ChunksController::update(int64_t maxDuration) { +void ChunksController::update( + int64_t maxDuration, int loadDistance, int centerX, int centerY +) { + generator->update(centerX, centerY, loadDistance); + int64_t mcstotal = 0; for (uint i = 0; i < MAX_WORK_PER_FRAME; i++) { diff --git a/src/logic/ChunksController.hpp b/src/logic/ChunksController.hpp index 5e607f51..85b00e8a 100644 --- a/src/logic/ChunksController.hpp +++ b/src/logic/ChunksController.hpp @@ -28,5 +28,9 @@ public: ~ChunksController(); /// @param maxDuration milliseconds reserved for chunks loading - void update(int64_t maxDuration); + void update( + int64_t maxDuration, + int loadDistance, + int centerX, + int centerY); }; diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 1badb0dc..1e947b42 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -10,6 +10,7 @@ #include "settings.hpp" #include "world/Level.hpp" #include "world/World.hpp" +#include "maths/voxmaths.hpp" #include "scripting/scripting.hpp" static debug::Logger logger("level-control"); @@ -38,7 +39,10 @@ void LevelController::update(float delta, bool input, bool pause) { position.z, settings.chunks.loadDistance.get() + settings.chunks.padding.get() * 2 ); - chunks->update(settings.chunks.loadSpeed.get()); + chunks->update( + settings.chunks.loadSpeed.get(), settings.chunks.loadDistance.get(), + floordiv(position.x, CHUNK_W), floordiv(position.z, CHUNK_D) + ); if (!pause) { // update all objects that needed diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index f699957d..c1e568fe 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -9,13 +9,35 @@ #include "voxels/Chunk.hpp" #include "world/generator/GeneratorDef.hpp" #include "util/timeutil.hpp" +#include "debug/Logger.hpp" + +static debug::Logger logger("world-generator"); static inline constexpr uint MAX_PARAMETERS = 16; +static inline constexpr uint MAX_CHUNK_PROTOTYPE_LEVELS = 8; WorldGenerator::WorldGenerator( const GeneratorDef& def, const Content* content, uint64_t seed ) - : def(def), content(content), seed(seed) { + : def(def), + content(content), + seed(seed), + surroundMap(0, MAX_CHUNK_PROTOTYPE_LEVELS) +{ + surroundMap.setOutCallback([this](int const x, int const z, int8_t) { + const auto& found = prototypes.find({x, z}); + if (found == prototypes.end()) { + logger.warning() << "unable to remove non-existing chunk prototype"; + return; + } + prototypes.erase({x, z}); + }); + surroundMap.setLevelCallback(1, [this](int const x, int const z) { + if (prototypes.find({x, z}) != prototypes.end()) { + return; + } + prototypes[{x, z}] = generatePrototype(x, z); + }); } static inline void generate_pole( @@ -78,7 +100,6 @@ static inline const Biome* choose_biome( std::unique_ptr WorldGenerator::generatePrototype( int chunkX, int chunkZ ) { - // timeutil::ScopeLogTimer log(666); auto biomeParams = def.script->generateParameterMaps( {chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed); const auto& biomes = def.script->getBiomes(); @@ -103,11 +124,23 @@ void WorldGenerator::generateHeightmap( prototype->level = ChunkPrototypeLevel::HEIGHTMAP; } +void WorldGenerator::update(int centerX, int centerY, int loadDistance) { + surroundMap.setCenter(centerX, centerY); + surroundMap.resize(loadDistance); + surroundMap.setCenter(centerX, centerY); +} + void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) { //timeutil::ScopeLogTimer log(555); + surroundMap.completeAt(chunkX, chunkZ); - auto prototype = generatePrototype(chunkX, chunkZ); - generateHeightmap(prototype.get(), chunkX, chunkZ); + const auto& found = prototypes.find({chunkX, chunkZ}); + if (found == prototypes.end()) { + throw std::runtime_error("no prototype found"); + } + + auto prototype = found->second.get(); + generateHeightmap(prototype, chunkX, chunkZ); const auto values = prototype->heightmap->getValues(); diff --git a/src/world/generator/WorldGenerator.hpp b/src/world/generator/WorldGenerator.hpp index 804cd4e9..2802baa6 100644 --- a/src/world/generator/WorldGenerator.hpp +++ b/src/world/generator/WorldGenerator.hpp @@ -3,10 +3,12 @@ #include #include #include +#include #include "constants.hpp" #include "typedefs.hpp" #include "voxels/voxel.hpp" +#include "SurroundMap.hpp" class Content; struct GeneratorDef; @@ -42,6 +44,10 @@ class WorldGenerator { const Content* content; /// @param seed world seed uint64_t seed; + /// @brief Chunk prototypes main storage + std::unordered_map> prototypes; + /// @brief Chunk prototypes loading surround map + SurroundMap surroundMap; /// @brief Generate chunk prototype (see ChunkPrototype) /// @param x chunk position X divided by CHUNK_W @@ -57,6 +63,8 @@ public: ); virtual ~WorldGenerator() = default; + virtual void update(int centerX, int centerY, int loadDistance); + /// @brief Generate complete chunk voxels /// @param voxels destinatiopn chunk voxels buffer /// @param x chunk position X divided by CHUNK_W