From e560236a8cb0c19c8a3103cee48332f9294b8632 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 17 Aug 2024 20:17:52 +0300 Subject: [PATCH] add heightmap write-only property 'noiseSeed' --- res/generators/default.lua | 6 +++- src/logic/scripting/lua/lua_custom_types.hpp | 12 +++++-- .../scripting/lua/lua_type_heightmap.cpp | 32 ++++++++++++++++--- src/logic/scripting/scripting.cpp | 5 +-- src/world/generator/GeneratorDef.hpp | 2 +- src/world/generator/WorldGenerator.cpp | 10 ++++-- src/world/generator/WorldGenerator.hpp | 2 +- 7 files changed, 56 insertions(+), 13 deletions(-) diff --git a/res/generators/default.lua b/res/generators/default.lua index a28b2e33..38c33ed0 100644 --- a/res/generators/default.lua +++ b/res/generators/default.lua @@ -7,15 +7,18 @@ layers = { {block="base:bazalt", height=1}, } -function generate_heightmap(x, y, w, h) +function generate_heightmap(x, y, w, h, seed) local umap = Heightmap(w, h) local vmap = Heightmap(w, h) + umap.noiseSeed = seed + vmap.noiseSeed = seed umap:noise({x+521, y+73}, 0.05, 1, 20.8) umap:noise({x+51, y+75}, 0.05, 1, 21.8) vmap:noise({x+521, y+70}, 0.1, 3, 35.8) vmap:noise({x+95, y+246}, 0.15, 3, 35.8) local map = Heightmap(w, h) + map.noiseSeed = seed map:noise({x, y}, 0.02, 7, 0.2) map:noise({x, y}, 0.06, 8, 0.4, umap, vmap) map:mul(0.5) @@ -23,6 +26,7 @@ function generate_heightmap(x, y, w, h) map:pow(2.0) local rivermap = Heightmap(w, h) + rivermap.noiseSeed = seed rivermap:noise({x+21, y+12}, 0.1, 4) rivermap:abs() rivermap:mul(2.0) diff --git a/src/logic/scripting/lua/lua_custom_types.hpp b/src/logic/scripting/lua/lua_custom_types.hpp index 1e6406b6..d6a7ba0b 100644 --- a/src/logic/scripting/lua/lua_custom_types.hpp +++ b/src/logic/scripting/lua/lua_custom_types.hpp @@ -6,6 +6,8 @@ #include "lua_commons.hpp" #include "maths/Heightmap.hpp" +struct fnl_state; + namespace lua { class Userdata { public: @@ -33,9 +35,9 @@ namespace lua { class LuaHeightmap : public Userdata { std::shared_ptr map; + std::unique_ptr noise; public: - LuaHeightmap(uint width, uint height) - : map(std::make_shared(width, height)) {} + LuaHeightmap(uint width, uint height); virtual ~LuaHeightmap(); @@ -63,6 +65,12 @@ namespace lua { return map; } + fnl_state* getNoise() { + return noise.get(); + } + + void setSeed(int64_t seed); + static int createMetatable(lua::State*); inline static std::string TYPENAME = "Heightmap"; }; diff --git a/src/logic/scripting/lua/lua_type_heightmap.cpp b/src/logic/scripting/lua/lua_type_heightmap.cpp index b2555103..4fc7d278 100644 --- a/src/logic/scripting/lua/lua_type_heightmap.cpp +++ b/src/logic/scripting/lua/lua_type_heightmap.cpp @@ -15,9 +15,16 @@ using namespace lua; -static fnl_state noise = fnlCreateState(); +LuaHeightmap::LuaHeightmap(uint width, uint height) + : map(std::make_shared(width, height)), + noise(std::make_unique(fnlCreateState())) +{} -LuaHeightmap::~LuaHeightmap() {; +LuaHeightmap::~LuaHeightmap() { +} + +void LuaHeightmap::setSeed(int64_t seed) { + noise->seed = seed; } static int l_dump(lua::State* L) { @@ -51,6 +58,7 @@ static int l_noise(lua::State* L) { uint w = heightmap->getWidth(); uint h = heightmap->getHeight(); auto heights = heightmap->getValues(); + auto noise = heightmap->getNoise(); auto offset = tovec<2>(L, 2); @@ -86,7 +94,7 @@ static int l_noise(lua::State* L) { v += shiftMapY->getValues()[i]; } - value += fnlGetNoise2D(&noise, u, v) / + value += fnlGetNoise2D(noise, u, v) / static_cast(1 << c) * multiplier; heights[i] = value; } @@ -185,6 +193,20 @@ static int l_meta_index(lua::State* L) { return 0; } +static int l_meta_newindex(lua::State* L) { + auto map = touserdata(L, 1); + if (map == nullptr) { + return 0; + } + if (isstring(L, 2)) { + auto fieldname = tostring(L, 2); + if (!std::strcmp(fieldname, "noiseSeed")) { + map->setSeed(tointeger(L, 3)); + } + } + return 0; +} + static int l_meta_tostring(lua::State* L) { auto map = touserdata(L, 1); if (map == nullptr) { @@ -202,11 +224,13 @@ static int l_meta_tostring(lua::State* L) { } int LuaHeightmap::createMetatable(lua::State* L) { - createtable(L, 0, 2); + createtable(L, 0, 3); pushcfunction(L, lua::wrap); setfield(L, "__tostring"); pushcfunction(L, lua::wrap); setfield(L, "__index"); + pushcfunction(L, lua::wrap); + setfield(L, "__newindex"); createtable(L, 0, 1); pushcfunction(L, lua::wrap); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 8705fb50..572c2ce2 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -703,14 +703,15 @@ public: {} std::shared_ptr generateHeightmap( - const glm::ivec2& offset, const glm::ivec2& size + const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed ) override { auto L = lua::get_main_thread(); lua::pushenv(L, *env); if (lua::getfield(L, "generate_heightmap")) { lua::pushivec_stack(L, offset); lua::pushivec_stack(L, size); - if (lua::call_nothrow(L, 4)) { + lua::pushinteger(L, seed); + if (lua::call_nothrow(L, 5)) { auto map = lua::touserdata(L, -1)->getHeightmap(); lua::pop(L, 2); return map; diff --git a/src/world/generator/GeneratorDef.hpp b/src/world/generator/GeneratorDef.hpp index 4b90997d..afb5eec3 100644 --- a/src/world/generator/GeneratorDef.hpp +++ b/src/world/generator/GeneratorDef.hpp @@ -23,7 +23,7 @@ public: virtual ~GeneratorScript() = default; virtual std::shared_ptr generateHeightmap( - const glm::ivec2& offset, const glm::ivec2& size) = 0; + const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0; virtual const std::vector& getLayers() const = 0; diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index 6c72aac0..d92050a8 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -15,10 +15,12 @@ WorldGenerator::WorldGenerator( } #include "util/timeutil.hpp" -void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ, int seed) { +void WorldGenerator::generate( + voxel* voxels, int chunkX, int chunkZ, uint64_t seed +) { timeutil::ScopeLogTimer log(555); auto heightmap = def.script->generateHeightmap( - {chunkX*CHUNK_W, chunkZ*CHUNK_D}, {CHUNK_W, CHUNK_D} + {chunkX*CHUNK_W, chunkZ*CHUNK_D}, {CHUNK_W, CHUNK_D}, seed ); auto values = heightmap->getValues(); const auto& layers = def.script->getLayers(); @@ -30,6 +32,7 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ, int seed) { for (uint z = 0; z < CHUNK_D; z++) { for (uint x = 0; x < CHUNK_W; x++) { + // generate water int height = values[z * CHUNK_W + x] * CHUNK_H; for (uint y = height+1; y <= seaLevel; y++) { voxels[vox_index(x, y, z)].id = baseWater; @@ -38,12 +41,15 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ, int seed) { uint y = height; uint layerExtension = 0; for (const auto& layer : layers) { + // skip layer if can't be generated under sea level if (y < seaLevel && !layer.below_sea_level) { layerExtension = std::max(0, layer.height); continue; } + uint layerHeight = layer.height; if (layerHeight == -1) { + // resizeable layer layerHeight = y - lastLayersHeight + 1; } else { layerHeight += layerExtension; diff --git a/src/world/generator/WorldGenerator.hpp b/src/world/generator/WorldGenerator.hpp index 98cb955c..67be501e 100644 --- a/src/world/generator/WorldGenerator.hpp +++ b/src/world/generator/WorldGenerator.hpp @@ -18,7 +18,7 @@ public: ); virtual ~WorldGenerator() = default; - virtual void generate(voxel* voxels, int x, int z, int seed); + virtual void generate(voxel* voxels, int x, int z, uint64_t seed); inline static std::string DEFAULT = "core:default"; };