refactor blocks layers

This commit is contained in:
MihailRis
2024-08-18 16:54:58 +03:00
parent af485dd7cb
commit 2a506e9891
4 changed files with 71 additions and 85 deletions
+2 -2
View File
@@ -42,11 +42,11 @@ end
function generate_heightmap(x, y, w, h, seed) function generate_heightmap(x, y, w, h, seed)
-- blocks per dot -- blocks per dot
-- 8 - linear interpolation is visible, but not so much (Minecraft) -- 8 - linear interpolation is visible, but not so much
-- 4 - high quality, but slower -- 4 - high quality, but slower
-- 2 - you really don't need it -- 2 - you really don't need it
-- 1 - please have mercy on your CPU -- 1 - please have mercy on your CPU
local bpd = 8 local bpd = 4
local map = _generate_heightmap( local map = _generate_heightmap(
math.floor(x/bpd), math.floor(y/bpd), math.floor(x/bpd), math.floor(y/bpd),
math.floor(w/bpd)+1, math.floor(h/bpd)+1, seed, bpd) math.floor(w/bpd)+1, math.floor(h/bpd)+1, seed, bpd)
+47 -60
View File
@@ -687,24 +687,18 @@ void scripting::load_entity_component(
class LuaGeneratorScript : public GeneratorScript { class LuaGeneratorScript : public GeneratorScript {
scriptenv env; scriptenv env;
std::vector<BlocksLayer> layers; BlocksLayers groundLayers;
std::vector<BlocksLayer> seaLayers; BlocksLayers seaLayers;
uint lastLayersHeight;
uint lastSeaLayersHeight;
uint seaLevel; uint seaLevel;
public: public:
LuaGeneratorScript( LuaGeneratorScript(
scriptenv env, scriptenv env,
std::vector<BlocksLayer> layers, BlocksLayers groundLayers,
std::vector<BlocksLayer> seaLayers, BlocksLayers seaLayers,
uint lastLayersHeight,
uint lastSeaLayersHeight,
uint seaLevel) uint seaLevel)
: env(std::move(env)), : env(std::move(env)),
layers(std::move(layers)), groundLayers(std::move(groundLayers)),
seaLayers(std::move(seaLayers)), seaLayers(std::move(seaLayers)),
lastLayersHeight(lastLayersHeight),
lastSeaLayersHeight(lastSeaLayersHeight),
seaLevel(seaLevel) seaLevel(seaLevel)
{} {}
@@ -728,30 +722,22 @@ public:
} }
void prepare(const Content* content) override { void prepare(const Content* content) override {
for (auto& layer : layers) { for (auto& layer : groundLayers.layers) {
layer.rt.id = content->blocks.require(layer.block).rt.id; layer.rt.id = content->blocks.require(layer.block).rt.id;
} }
for (auto& layer : seaLayers) { for (auto& layer : seaLayers.layers) {
layer.rt.id = content->blocks.require(layer.block).rt.id; layer.rt.id = content->blocks.require(layer.block).rt.id;
} }
} }
const std::vector<BlocksLayer>& getLayers() const override { const BlocksLayers& getGroundLayers() const override {
return layers; return groundLayers;
} }
const std::vector<BlocksLayer>& getSeaLayers() const override { const BlocksLayers& getSeaLayers() const override {
return seaLayers; return seaLayers;
} }
uint getLastLayersHeight() const override {
return lastLayersHeight;
}
uint getLastSeaLayersHeight() const override {
return lastSeaLayersHeight;
}
uint getSeaLevel() const override { uint getSeaLevel() const override {
return seaLevel; return seaLevel;
} }
@@ -784,6 +770,32 @@ static BlocksLayer load_layer(
return BlocksLayer {name, height, belowSeaLevel, {}}; return BlocksLayer {name, height, belowSeaLevel, {}};
} }
static inline BlocksLayers load_layers(
lua::State* L, const std::string& fieldname
) {
uint lastLayersHeight = 0;
bool hasResizeableLayer = false;
std::vector<BlocksLayer> layers;
if (lua::getfield(L, fieldname)) {
int len = lua::objlen(L, -1);
for (int i = 1; i <= len; i++) {
lua::rawgeti(L, i);
try {
layers.push_back(
load_layer(L, -1, lastLayersHeight, hasResizeableLayer));
} catch (const std::runtime_error& err) {
lua::pop(L, 2);
throw std::runtime_error(
fieldname+" #"+std::to_string(i)+": "+err.what());
}
lua::pop(L);
}
lua::pop(L);
}
return BlocksLayers {std::move(layers), lastLayersHeight};
}
std::unique_ptr<GeneratorScript> scripting::load_generator( std::unique_ptr<GeneratorScript> scripting::load_generator(
const fs::path& file const fs::path& file
) { ) {
@@ -800,50 +812,25 @@ std::unique_ptr<GeneratorScript> scripting::load_generator(
lua::pop(L); lua::pop(L);
} }
uint lastLayersHeight = 0; uint lastGroundLayersHeight = 0;
uint lastSeaLayersHeight = 0; uint lastSeaLayersHeight = 0;
bool hasResizeableLayer = false; bool hasResizeableGroundLayer = false;
bool hasResizeableSeaLayer = false; bool hasResizeableSeaLayer = false;
std::vector<BlocksLayer> layers; BlocksLayers groundLayers;
std::vector<BlocksLayer> seaLayers; BlocksLayers seaLayers;
if (lua::getfield(L, "layers")) { try {
int len = lua::objlen(L, -1); groundLayers = load_layers(L, "layers");
for (int i = 1; i <= len; i++) { seaLayers = load_layers(L, "sea_layers");
lua::rawgeti(L, i); } catch (const std::runtime_error& err) {
try {
layers.push_back(
load_layer(L, -1, lastLayersHeight, hasResizeableLayer));
} catch (const std::runtime_error& err) {
lua::pop(L, 2);
throw std::runtime_error(
"layer #"+std::to_string(i)+": "+err.what());
}
lua::pop(L);
}
lua::pop(L);
}
if (lua::getfield(L, "sea_layers")) {
int len = lua::objlen(L, -1);
for (int i = 1; i <= len; i++) {
lua::rawgeti(L, i);
try {
seaLayers.push_back(
load_layer(L, -1, lastSeaLayersHeight, hasResizeableSeaLayer));
} catch (const std::runtime_error& err) {
lua::pop(L, 2);
throw std::runtime_error(
"sea layer #"+std::to_string(i)+": "+err.what());
}
lua::pop(L);
}
lua::pop(L); lua::pop(L);
throw std::runtime_error(file.u8string()+": "+err.what());
} }
lua::pop(L); lua::pop(L);
return std::make_unique<LuaGeneratorScript>( return std::make_unique<LuaGeneratorScript>(
std::move(env), std::move(env),
std::move(layers), std::move(seaLayers), std::move(groundLayers),
lastLayersHeight, lastSeaLayersHeight, std::move(seaLayers),
seaLevel); seaLevel);
} }
+7 -6
View File
@@ -18,6 +18,11 @@ struct BlocksLayer {
} rt; } rt;
}; };
struct BlocksLayers {
std::vector<BlocksLayer> layers;
uint lastLayersHeight;
};
class GeneratorScript { class GeneratorScript {
public: public:
virtual ~GeneratorScript() = default; virtual ~GeneratorScript() = default;
@@ -25,12 +30,8 @@ public:
virtual std::shared_ptr<Heightmap> generateHeightmap( virtual std::shared_ptr<Heightmap> generateHeightmap(
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0; const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0;
virtual const std::vector<BlocksLayer>& getLayers() const = 0; virtual const BlocksLayers& getGroundLayers() const = 0;
virtual const std::vector<BlocksLayer>& getSeaLayers() const = 0; virtual const BlocksLayers& getSeaLayers() const = 0;
/// @brief Total height of all layers after resizeable one
virtual uint getLastLayersHeight() const = 0;
virtual uint getLastSeaLayersHeight() const = 0;
virtual uint getSeaLevel() const = 0; virtual uint getSeaLevel() const = 0;
+15 -17
View File
@@ -9,31 +9,32 @@
#include "voxels/voxel.hpp" #include "voxels/voxel.hpp"
#include "world/generator/GeneratorDef.hpp" #include "world/generator/GeneratorDef.hpp"
WorldGenerator::WorldGenerator( WorldGenerator::WorldGenerator(const GeneratorDef& def, const Content* content)
const GeneratorDef& def, : def(def), content(content) {
const Content* content
) : def(def), content(content) {
} }
static inline void generate_pole( static inline void generate_pole(
const std::vector<BlocksLayer>& layers, const BlocksLayers& layers,
int height, int bottom, int seaLevel, int lastLayersHeight, int height,
int bottom,
int seaLevel,
voxel* voxels, voxel* voxels,
int x, int z int x,
int z
) { ) {
uint y = height; uint y = height;
uint layerExtension = 0; uint layerExtension = 0;
for (const auto& layer : layers) { for (const auto& layer : layers.layers) {
// skip layer if can't be generated under sea level // skip layer if can't be generated under sea level
if (y < seaLevel && !layer.below_sea_level) { if (y < seaLevel && !layer.below_sea_level) {
layerExtension = std::max(0, layer.height); layerExtension = std::max(0, layer.height);
continue; continue;
} }
int layerHeight = layer.height; int layerHeight = layer.height;
if (layerHeight == -1) { if (layerHeight == -1) {
// resizeable layer // resizeable layer
layerHeight = y - lastLayersHeight - bottom + 1; layerHeight = y - layers.lastLayersHeight - bottom + 1;
} else { } else {
layerHeight += layerExtension; layerHeight += layerExtension;
} }
@@ -52,15 +53,12 @@ void WorldGenerator::generate(
) { ) {
timeutil::ScopeLogTimer log(555); timeutil::ScopeLogTimer log(555);
auto heightmap = def.script->generateHeightmap( auto heightmap = def.script->generateHeightmap(
{chunkX*CHUNK_W, chunkZ*CHUNK_D}, {CHUNK_W, CHUNK_D}, seed {chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed
); );
auto values = heightmap->getValues(); auto values = heightmap->getValues();
const auto& layers = def.script->getLayers(); const auto& groundLayers = def.script->getGroundLayers();
const auto& seaLayers = def.script->getSeaLayers(); const auto& seaLayers = def.script->getSeaLayers();
uint lastLayersHeight = def.script->getLastLayersHeight();
uint lastSeaLayersHeight = def.script->getLastSeaLayersHeight();
uint seaLevel = def.script->getSeaLevel(); uint seaLevel = def.script->getSeaLevel();
std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL); std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL);
@@ -70,8 +68,8 @@ void WorldGenerator::generate(
int height = values[z * CHUNK_W + x] * CHUNK_H; int height = values[z * CHUNK_W + x] * CHUNK_H;
height = std::max(0, height); height = std::max(0, height);
generate_pole(seaLayers, seaLevel, height, seaLevel, lastSeaLayersHeight, voxels, x, z); generate_pole(seaLayers, seaLevel, height, seaLevel, voxels, x, z);
generate_pole(layers, height, 0, seaLevel, lastLayersHeight, voxels, x, z); generate_pole(groundLayers, height, 0, seaLevel, voxels, x, z);
} }
} }
} }