implement inter-chunk structure generation
This commit is contained in:
parent
03ba7c9539
commit
a413c5d09e
@ -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
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -121,6 +121,7 @@ public:
|
||||
|
||||
lua::rawgeti(L, 2);
|
||||
glm::ivec3 pos = lua::tovec3(L, -1);
|
||||
lua::pop(L);
|
||||
|
||||
lua::pop(L);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user