From a413c5d09ea07771e1296ab582cb49c4052c33fc Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 21 Sep 2024 20:50:12 +0300 Subject: [PATCH] implement inter-chunk structure generation --- res/generators/default.lua | 11 +++-- .../lua/usertypes/lua_type_heightmap.cpp | 10 +++++ .../scripting/scripting_world_generation.cpp | 1 + src/util/listutil.hpp | 9 +++- src/world/generator/WorldGenerator.cpp | 45 +++++++++++++++++-- 5 files changed, 67 insertions(+), 9 deletions(-) diff --git a/res/generators/default.lua b/res/generators/default.lua index d6058b4b..254820cd 100644 --- a/res/generators/default.lua +++ b/res/generators/default.lua @@ -68,10 +68,13 @@ end function place_structures(x, z, w, d, seed) local placements = {} - local px = math.random() * w - local py = 200; - local pz = math.random() * d - table.insert(placements, {0, {px, py, pz}}) + local hmap = generate_heightmap(x, z, w, d, seed) + for i=0,math.floor(math.random()*3)+5 do + local px = math.random() * w + local pz = math.random() * d + local py = hmap:at(px, pz) * 256 + table.insert(placements, {0, {px-8, py, pz-8}}) + end return placements end diff --git a/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp b/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp index fc766c53..3982a5be 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_heightmap.cpp @@ -70,6 +70,15 @@ static int l_dump(lua::State* L) { return 0; } +static int l_at(lua::State* L) { + if (auto heightmap = touserdata(L, 1)) { + int x = lua::tointeger(L, 2); + int y = lua::tointeger(L, 3); + return lua::pushnumber(L, heightmap->getHeightmap()->get(x, y)); + } + return 0; +} + template static int l_noise(lua::State* L) { if (auto heightmap = touserdata(L, 1)) { @@ -208,6 +217,7 @@ static std::unordered_map methods { {"abs", lua::wrap>}, {"resize", lua::wrap}, {"crop", lua::wrap}, + {"at", lua::wrap}, }; static int l_meta_meta_call(lua::State* L) { diff --git a/src/logic/scripting/scripting_world_generation.cpp b/src/logic/scripting/scripting_world_generation.cpp index 4551a0c9..2eb4fd39 100644 --- a/src/logic/scripting/scripting_world_generation.cpp +++ b/src/logic/scripting/scripting_world_generation.cpp @@ -121,6 +121,7 @@ public: lua::rawgeti(L, 2); glm::ivec3 pos = lua::tovec3(L, -1); + lua::pop(L); lua::pop(L); diff --git a/src/util/listutil.hpp b/src/util/listutil.hpp index dec9499b..b3df6deb 100644 --- a/src/util/listutil.hpp +++ b/src/util/listutil.hpp @@ -1,15 +1,20 @@ #pragma once #include -#include #include #include namespace util { template - bool contains(const std::vector& vec, const T& value) { + inline bool contains(const std::vector& vec, const T& value) { return std::find(vec.begin(), vec.end(), value) != vec.end(); } + template + inline void concat(std::vector& a, const std::vector& b) { + a.reserve(a.size() + b.size()); + a.insert(a.end(), b.begin(), b.end()); + } + std::string to_string(const std::vector& vec); } diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index 2e6462e8..d22512b4 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -10,6 +10,7 @@ #include "GeneratorDef.hpp" #include "VoxelStructure.hpp" #include "util/timeutil.hpp" +#include "util/listutil.hpp" #include "debug/Logger.hpp" static debug::Logger logger("world-generator"); @@ -132,15 +133,49 @@ std::unique_ptr WorldGenerator::generatePrototype( return std::make_unique(); } +inline AABB gen_chunk_aabb(int chunkX, int chunkZ) { + return AABB({chunkX * CHUNK_W, 0, chunkZ * CHUNK_D}, + {(chunkX + 1)*CHUNK_W, 256, (chunkZ + 1) * CHUNK_D}); +} + void WorldGenerator::generateStructures( ChunkPrototype& prototype, int chunkX, int chunkZ ) { if (prototype.level >= ChunkPrototypeLevel::STRUCTURES) { return; } - prototype.structures = def.script->placeStructures( + util::concat(prototype.structures, def.script->placeStructures( {chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed - ); + )); + for (const auto& placement : prototype.structures) { + const auto& offset = placement.position; + if (placement.structure < 0 || placement.structure >= structures.size()) { + logger.error() << "invalid structure index " << placement.structure; + continue; + } + auto& structure = *structures[placement.structure]; + auto position = glm::ivec3(chunkX * CHUNK_W, 0, chunkZ * CHUNK_D)+offset; + auto size = structure.getSize() + glm::ivec3(0, CHUNK_H, 0); + AABB aabb(position, position + size); + for (int lcz = -1; lcz <= 1; lcz++) { + for (int lcx = -1; lcx <= 1; lcx++) { + if (lcx == 0 && lcz == 0) { + continue; + } + auto& otherPrototype = requirePrototype( + chunkX + lcx, chunkZ + lcz + ); + auto chunkAABB = gen_chunk_aabb(chunkX + lcx, chunkZ + lcz); + if (chunkAABB.intersect(aabb)) { + otherPrototype.structures.emplace_back( + placement.structure, + placement.position - + glm::ivec3(lcx * CHUNK_W, 0, lcz * CHUNK_D) + ); + } + } + } + } prototype.level = ChunkPrototypeLevel::STRUCTURES; } @@ -224,6 +259,7 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) { for (const auto& placement : prototype.structures) { if (placement.structure < 0 || placement.structure >= structures.size()) { logger.error() << "invalid structure index " << placement.structure; + continue; } auto& structure = *structures[placement.structure]; auto& structVoxels = structure.getRuntimeVoxels(); @@ -244,8 +280,11 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) { if (sx < 0 || sx >= CHUNK_W) { continue; } - voxels[vox_index(sx, sy, sz)] = + const auto& structVoxel = structVoxels[vox_index(x, y, z, size.x, size.z)]; + if (structVoxel.id) { + voxels[vox_index(sx, sy, sz)] = structVoxel; + } } } }