implement inter-chunk structure generation

This commit is contained in:
MihailRis 2024-09-21 20:50:12 +03:00
parent 03ba7c9539
commit a413c5d09e
5 changed files with 67 additions and 9 deletions

View File

@ -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

View File

@ -70,6 +70,15 @@ static int l_dump(lua::State* L) {
return 0;
}
static int l_at(lua::State* L) {
if (auto heightmap = touserdata<LuaHeightmap>(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<fnl_noise_type noise_type>
static int l_noise(lua::State* L) {
if (auto heightmap = touserdata<LuaHeightmap>(L, 1)) {
@ -208,6 +217,7 @@ static std::unordered_map<std::string, lua_CFunction> methods {
{"abs", lua::wrap<l_unaryop_func<util::abs>>},
{"resize", lua::wrap<l_resize>},
{"crop", lua::wrap<l_crop>},
{"at", lua::wrap<l_at>},
};
static int l_meta_meta_call(lua::State* L) {

View File

@ -121,6 +121,7 @@ public:
lua::rawgeti(L, 2);
glm::ivec3 pos = lua::tovec3(L, -1);
lua::pop(L);
lua::pop(L);

View File

@ -1,15 +1,20 @@
#pragma once
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
namespace util {
template <class T>
bool contains(const std::vector<T>& vec, const T& value) {
inline bool contains(const std::vector<T>& vec, const T& value) {
return std::find(vec.begin(), vec.end(), value) != vec.end();
}
template <class T>
inline void concat(std::vector<T>& a, const std::vector<T>& b) {
a.reserve(a.size() + b.size());
a.insert(a.end(), b.begin(), b.end());
}
std::string to_string(const std::vector<std::string>& vec);
}

View File

@ -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<ChunkPrototype> WorldGenerator::generatePrototype(
return std::make_unique<ChunkPrototype>();
}
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;
}
}
}
}