add debug world generator visualization

This commit is contained in:
MihailRis 2024-09-30 15:14:34 +03:00
parent 88752806e6
commit 75d66b644b
11 changed files with 116 additions and 9 deletions

View File

@ -1,9 +1,8 @@
BLOCKS_PER_CHUNK = 65536
local _, dir = parse_path(__DIR__)
ores = file.read_combined_list(dir.."/ores.json")
local function place_ores(placements, x, z, w, d, seed, hmap, chunk_height)
local BLOCKS_PER_CHUNK = w * d * chunk_height
for _, ore in ipairs(ores) do
local count = BLOCKS_PER_CHUNK / ore.rarity

View File

@ -17,6 +17,7 @@
#include "graphics/core/Mesh.hpp"
#include "graphics/core/Shader.hpp"
#include "graphics/core/Texture.hpp"
#include "graphics/core/ImageData.hpp"
#include "graphics/render/WorldRenderer.hpp"
#include "graphics/ui/elements/InventoryView.hpp"
#include "graphics/ui/elements/Menu.hpp"
@ -29,6 +30,8 @@
#include "items/Inventory.hpp"
#include "items/ItemDef.hpp"
#include "logic/scripting/scripting.hpp"
#include "logic/LevelController.hpp"
#include "world/generator/WorldGenerator.hpp"
#include "maths/voxmaths.hpp"
#include "objects/Player.hpp"
#include "physics/Hitbox.hpp"
@ -140,12 +143,16 @@ std::shared_ptr<InventoryView> Hud::createHotbar() {
return view;
}
static constexpr uint WORLDGEN_IMG_SIZE = 64U;
Hud::Hud(Engine* engine, LevelFrontend* frontend, Player* player)
: assets(engine->getAssets()),
gui(engine->getGUI()),
frontend(frontend),
player(player)
{
player(player),
debugImgWorldGen(std::make_unique<ImageData>(
ImageFormat::rgba8888, WORLDGEN_IMG_SIZE, WORLDGEN_IMG_SIZE
)) {
contentAccess = createContentAccess();
contentAccess->setId("hud.content-access");
contentAccessPanel = std::make_shared<Panel>(
@ -177,6 +184,14 @@ Hud::Hud(Engine* engine, LevelFrontend* frontend, Player* player)
dplotter->setGravity(Gravity::bottom_right);
dplotter->setInteractive(false);
add(HudElement(hud_element_mode::permanent, nullptr, dplotter, true));
assets->store(Texture::from(debugImgWorldGen.get()), DEBUG_WORLDGEN_IMAGE);
add(HudElement(hud_element_mode::permanent, nullptr,
guiutil::create(
"<image src='"+DEBUG_WORLDGEN_IMAGE+
"' pos='0' size='256' gravity='top-right' margin='0,20,0,0'/>"
), true));
}
Hud::~Hud() {
@ -250,6 +265,40 @@ void Hud::updateHotbarControl() {
}
}
void Hud::updateWorldGenDebugVisualization() {
auto level = frontend->getLevel();
auto generator =
frontend->getController()->getChunksController()->getGenerator();
auto debugInfo = generator->createDebugInfo();
uint width = debugImgWorldGen->getWidth();
uint height = debugImgWorldGen->getHeight();
ubyte* data = debugImgWorldGen->getData();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (x >= debugInfo.areaWidth || y >= debugInfo.areaHeight) {
for (int i = 0; i < 4; i++) {
data[(y * width + x) * 4 + i] = 0;
}
continue;
}
int cx = x + debugInfo.areaOffsetX;
int cz = y + debugInfo.areaOffsetY;
auto value = debugInfo.areaLevels[y * debugInfo.areaWidth + x] * 35;
// Chunk is already generated
if (level->chunks->getChunk(cx, cz)) {
value = 255;
}
for (int i = 0; i < 3; i++) {
data[(y * width + x) * 4 + i] = value;
}
data[(y * width + x) * 4 + 3] = 100;
}
}
auto texture = assets->get<Texture>(DEBUG_WORLDGEN_IMAGE);
texture->reload(*debugImgWorldGen);
}
void Hud::update(bool visible) {
auto level = frontend->getLevel();
auto menu = gui->getMenu();
@ -296,6 +345,10 @@ void Hud::update(bool visible) {
}
}
cleanup();
if (player->debug) {
updateWorldGenDebugVisualization();
}
}
/// @brief Show inventory on the screen and turn on inventory mode blocking movement

View File

@ -18,6 +18,7 @@ class LevelFrontend;
class UiDocument;
class DrawContext;
class Viewport;
class ImageData;
namespace gui {
class GUI;
@ -108,6 +109,8 @@ class Hud : public util::ObjectsKeeper {
/// @brief UI element will be dynamicly positioned near to inventory or in screen center
std::shared_ptr<gui::UINode> secondUI = nullptr;
std::unique_ptr<ImageData> debugImgWorldGen;
std::shared_ptr<gui::InventoryView> createContentAccess();
std::shared_ptr<gui::InventoryView> createHotbar();
@ -117,6 +120,7 @@ class Hud : public util::ObjectsKeeper {
void cleanup();
void showExchangeSlot();
void updateWorldGenDebugVisualization();
public:
Hud(Engine* engine, LevelFrontend* frontend, Player* player);
~Hud();
@ -167,4 +171,7 @@ public:
Player* getPlayer() const;
std::shared_ptr<Inventory> getBlockInventory();
/// @brief Runtime updating debug visualization texture
inline static std::string DEBUG_WORLDGEN_IMAGE = "#debug.img.worldgen";
};

View File

@ -41,6 +41,12 @@ void GLTexture::unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
void GLTexture::reload(const ImageData& image) {
width = image.getWidth();
height = image.getHeight();
reload(image.getData());
}
void GLTexture::reload(const ubyte* data) {
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,

View File

@ -16,6 +16,8 @@ public:
void setNearestFilter();
virtual void reload(const ImageData& image) override;
virtual std::unique_ptr<ImageData> readData() override;
virtual uint getId() const override;

View File

@ -20,6 +20,8 @@ public:
virtual void bind() = 0;
virtual void unbind() = 0;
virtual void reload(const ImageData& image) = 0;
virtual std::unique_ptr<ImageData> readData() = 0;
virtual uint getWidth() const {

View File

@ -33,4 +33,8 @@ public:
int loadDistance,
int centerX,
int centerY);
const WorldGenerator* getGenerator() const {
return generator.get();
}
};

View File

@ -95,6 +95,10 @@ BlocksController* LevelController::getBlocksController() {
return blocks.get();
}
ChunksController* LevelController::getChunksController() {
return chunks.get();
}
PlayerController* LevelController::getPlayerController() {
return player.get();
}

View File

@ -34,5 +34,6 @@ public:
Player* getPlayer();
BlocksController* getBlocksController();
ChunksController* getChunksController();
PlayerController* getPlayerController();
};

View File

@ -355,3 +355,21 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
}
}
}
WorldGenDebugInfo WorldGenerator::createDebugInfo() const {
const auto& area = surroundMap.getArea();
const auto& levels = area.getBuffer();
auto values = std::make_unique<ubyte[]>(area.getWidth()*area.getHeight());
for (uint i = 0; i < levels.size(); i++) {
values[i] = levels[i];
}
return WorldGenDebugInfo {
area.getOffsetX(),
area.getOffsetY(),
static_cast<uint>(area.getWidth()),
static_cast<uint>(area.getHeight()),
std::move(values)
};
}

View File

@ -34,6 +34,14 @@ struct ChunkPrototype {
std::vector<StructurePlacement> structures;
};
struct WorldGenDebugInfo {
int areaOffsetX;
int areaOffsetY;
uint areaWidth;
uint areaHeight;
std::unique_ptr<ubyte[]> areaLevels;
};
/// @brief High-level world generation controller
class WorldGenerator {
/// @param def generator definition
@ -80,5 +88,8 @@ public:
/// @param z chunk position Y divided by CHUNK_D
void generate(voxel* voxels, int x, int z);
WorldGenDebugInfo createDebugInfo() const;
/// @brief Default generator name // TODO: move to config
inline static std::string DEFAULT = "core:default";
};