From 88544183d054f81785b0a41fda0b4bb8278d522b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 29 Dec 2025 20:41:47 +0300 Subject: [PATCH] stabilize delays of chunks meshes building --- src/assets/AssetsLoader.cpp | 2 +- src/graphics/render/BlocksRenderer.cpp | 71 ++++----- src/graphics/render/BlocksRenderer.hpp | 9 +- src/graphics/render/ChunksRenderer.cpp | 44 +++--- src/graphics/render/ChunksRenderer.hpp | 10 +- src/graphics/render/commons.hpp | 10 ++ src/util/ObjectsPool.hpp | 4 + src/util/ThreadPool.hpp | 8 +- src/voxels/Chunks.cpp | 196 ++++++++++++++++--------- src/voxels/Chunks.hpp | 31 +++- src/voxels/VoxelsVolume.cpp | 28 ---- src/voxels/VoxelsVolume.hpp | 111 ++++++++++++-- src/world/files/WorldConverter.cpp | 2 +- 13 files changed, 335 insertions(+), 191 deletions(-) delete mode 100644 src/voxels/VoxelsVolume.cpp diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index f717c1e5b..a6af6067f 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -353,7 +353,7 @@ std::shared_ptr AssetsLoader::startTask(runnable onDone) { auto pool = std::make_shared>( "assets-loader-pool", - [=]() { return std::make_shared(this); }, + [=]() { return std::make_unique(this); }, [this](assetload::postfunc&& func) { func(&assets); } ); pool->setOnComplete(std::move(onDone)); diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 64f8811f1..16d8cf4a0 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -42,21 +42,22 @@ void BlocksRenderer::vertex( const glm::vec3& normal, float emission ) { - vertexBuffer[vertexCount].position = coord; - vertexBuffer[vertexCount].uv = {u,v}; - - vertexBuffer[vertexCount].normal[0] = static_cast(normal.r * 127 + 128); - vertexBuffer[vertexCount].normal[1] = static_cast(normal.g * 127 + 128); - vertexBuffer[vertexCount].normal[2] = static_cast(normal.b * 127 + 128); - vertexBuffer[vertexCount].normal[3] = static_cast(emission * 255); - - vertexBuffer[vertexCount].color[0] = static_cast(light.r * 255); - vertexBuffer[vertexCount].color[1] = static_cast(light.g * 255); - vertexBuffer[vertexCount].color[2] = static_cast(light.b * 255); - vertexBuffer[vertexCount].color[3] = static_cast(light.a * 255); - - vertexCount++; + vertexBuffer[vertexCount++] = { + coord, + {u, v}, + { + static_cast(light.r * 255), + static_cast(light.g * 255), + static_cast(light.b * 255), + static_cast(light.a * 255), + }, { + static_cast(normal.x * 127 + 128), + static_cast(normal.y * 127 + 128), + static_cast(normal.z * 127 + 128), + static_cast(emission * 255) + } + }; } void BlocksRenderer::index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f) { @@ -434,28 +435,11 @@ void BlocksRenderer::blockCube( } } -bool BlocksRenderer::isOpenForLight(int x, int y, int z) const { - blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x, - y, - chunk->z * CHUNK_D + z); - if (id == BLOCK_VOID) { - return false; - } - const Block& block = *blockDefsCache[id]; - if (block.lightPassing) { - return true; - } - return !id; -} - glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const { - if (isOpenForLight(x, y, z)) { - light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y, - chunk->z * CHUNK_D + z); - return Lightmap::extractNormalized(light); - } else { - return glm::vec4(0.0f); - } + light_t light = voxelsBuffer->pickLight( + chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z + ); + return light ? Lightmap::extractNormalized(light) : glm::vec4(0.0f); } glm::vec4 BlocksRenderer::pickLight(const glm::ivec3& coord) const { @@ -694,7 +678,9 @@ SortingMeshData BlocksRenderer::renderTranslucent( return sortingMesh; } -void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) { +void BlocksRenderer::build( + const Chunk* chunk, const VoxelsRenderVolume& volume +) { this->chunk = chunk; this->voxelsBuffer = &volume; if (voxelsBuffer->pickBlockId( @@ -707,16 +693,17 @@ void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) { int totalBegin = chunk->bottom * (CHUNK_W * CHUNK_D); int totalEnd = chunk->top * (CHUNK_W * CHUNK_D); - + bool hasTranslucent = false; int beginEnds[256][2] {}; for (int i = totalBegin; i < totalEnd; i++) { const voxel& vox = voxels[i]; blockid_t id = vox.id; const auto& def = *blockDefsCache[id]; const auto& variant = def.getVariantByBits(vox.state.userbits); + hasTranslucent = def.translucent || hasTranslucent; if (beginEnds[variant.drawGroup][0] == 0) { - beginEnds[variant.drawGroup][0] = i+1; + beginEnds[variant.drawGroup][0] = i + 1; } beginEnds[variant.drawGroup][1] = i; } @@ -729,7 +716,11 @@ void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) { denseRender = false; densePass = false; - sortingMesh = renderTranslucent(voxels, beginEnds); + if (hasTranslucent) { + sortingMesh = renderTranslucent(voxels, beginEnds); + } else { + sortingMesh = {}; + } overflow = false; vertexCount = 0; @@ -775,7 +766,7 @@ ChunkMeshData BlocksRenderer::createMesh() { } ChunkMesh BlocksRenderer::render( - const Chunk* chunk, const VoxelsVolume& volume + const Chunk* chunk, const VoxelsRenderVolume& volume ) { build(chunk, volume); diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 1eee81783..52eebeb26 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -17,7 +17,6 @@ class Content; class Block; class Chunk; class Chunks; -class VoxelsVolume; class ContentGfxCache; struct UVRegion; @@ -31,9 +30,9 @@ public: ); ~BlocksRenderer(); - void build(const Chunk* chunk, const VoxelsVolume& volume); + void build(const Chunk* chunk, const VoxelsRenderVolume& volume); ChunkMesh render( - const Chunk* chunk, const VoxelsVolume& volume + const Chunk* chunk, const VoxelsRenderVolume& volume ); ChunkMeshData createMesh(); @@ -58,7 +57,7 @@ private: bool densePass = false; bool denseRender = false; const Chunk* chunk = nullptr; - const VoxelsVolume* voxelsBuffer = nullptr; + const VoxelsRenderVolume* voxelsBuffer = nullptr; const Block* const* blockDefsCache; const ContentGfxCache& cache; @@ -143,8 +142,6 @@ private: bool ao ); - bool isOpenForLight(int x, int y, int z) const; - // Does block allow to see other blocks sides (is it transparent) inline bool isOpen(const glm::ivec3& pos, const Block& def, const Variant& variant) const { auto vox = voxelsBuffer->pickBlock( diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index b906b9b5e..31d44cf13 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -19,6 +19,8 @@ static debug::Logger logger("chunks-render"); size_t ChunksRenderer::visibleChunks = 0; +static constexpr inline size_t MAX_CHUNKS_ENQUEUED_IN_FRAME = 4; + class RendererWorker : public util::Worker { BlocksRenderer renderer; public: @@ -51,8 +53,7 @@ public: } }; -static util::ObjectsPool voxelsVolumesPool {}; -static inline const int VOXELS_BUFFER_PADDING = 2; +static util::ObjectsPool voxelsVolumesPool {}; ChunksRenderer::ChunksRenderer( const Level* level, @@ -69,7 +70,7 @@ ChunksRenderer::ChunksRenderer( threadPool( "chunks-render-pool", [&]() { - return std::make_shared( + return std::make_unique( *level, cache, settings ); }, @@ -105,14 +106,10 @@ ChunksRenderer::ChunksRenderer( ChunksRenderer::~ChunksRenderer() = default; -std::shared_ptr ChunksRenderer::prepareVoxelsVolume( +std::shared_ptr ChunksRenderer::prepareVoxelsVolume( const Chunk& chunk ) { - auto voxelsBuffer = voxelsVolumesPool.create( - CHUNK_W + VOXELS_BUFFER_PADDING * 2, - CHUNK_H, - CHUNK_D + VOXELS_BUFFER_PADDING * 2 - ); + auto voxelsBuffer = voxelsVolumesPool.create(); voxelsBuffer->setPosition( chunk.x * CHUNK_W - VOXELS_BUFFER_PADDING, 0, chunk.z * CHUNK_D - VOXELS_BUFFER_PADDING @@ -123,8 +120,10 @@ std::shared_ptr ChunksRenderer::prepareVoxelsVolume( return voxelsBuffer; } +#include "util/timeutil.hpp" + const Mesh* ChunksRenderer::render( - const std::shared_ptr& chunk, bool important + const std::shared_ptr& chunk, bool important, bool lowPriority ) { glm::ivec2 key(chunk->x, chunk->z); chunk->flags.modified = false; @@ -136,16 +135,16 @@ const Mesh* ChunksRenderer::render( std::move(mesh.mesh), std::move(mesh.sortingMeshData), nullptr}; return meshes[key].mesh.get(); } - if (inwork.find(key) != inwork.end()) { + if (inwork.find(key) != inwork.end() || + ((inwork.size() >= threadPool.getWorkTotal() || + enqueuedInFrame >= MAX_CHUNKS_ENQUEUED_IN_FRAME) && + lowPriority)) { return nullptr; } + enqueuedInFrame++; auto voxelsBuffer = prepareVoxelsVolume(*chunk); - inwork[key] = true; - chunks.getVoxels( - *voxelsBuffer, settings.graphics.backlight.get(), chunk->top + 1 - ); - threadPool.enqueueJob({chunk, std::move(voxelsBuffer)}); + inwork[key] = true; return nullptr; } @@ -163,20 +162,21 @@ void ChunksRenderer::clear() { } const Mesh* ChunksRenderer::getOrRender( - const std::shared_ptr& chunk, bool important + const std::shared_ptr& chunk, bool important, bool lowPriority ) { auto found = meshes.find(glm::ivec2(chunk->x, chunk->z)); if (found == meshes.end()) { - return render(chunk, important); + return render(chunk, important, lowPriority); } if (chunk->flags.modified && chunk->flags.lighted) { - render(chunk, important); + render(chunk, important, lowPriority); } return found->second.mesh.get(); } void ChunksRenderer::update() { threadPool.pullResults(); + enqueuedInFrame = 0; } const Mesh* ChunksRenderer::retrieveChunk( @@ -202,7 +202,11 @@ const Mesh* ChunksRenderer::retrieveChunk( (chunk->z + 0.5f) * CHUNK_D ) ); - auto mesh = getOrRender(chunk, distance < CHUNK_W * 1.5f); + auto mesh = getOrRender( + chunk, + distance < CHUNK_W * 1.5f, + distance > CHUNK_W * settings.chunks.loadDistance.get() * 0.5 + ); if (mesh == nullptr) { return nullptr; } diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index 9794a8405..396a29c12 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -21,7 +21,6 @@ class Chunks; class Frustum; class BlocksRenderer; class ContentGfxCache; -class VoxelsVolume; struct EngineSettings; struct ChunksSortEntry { @@ -41,7 +40,7 @@ struct RendererResult { struct RendererJob { std::shared_ptr chunk; - std::shared_ptr volume; + std::shared_ptr volume; }; class ChunksRenderer { @@ -58,7 +57,8 @@ class ChunksRenderer { const Mesh* retrieveChunk( size_t index, const Camera& camera, bool culling ); - std::shared_ptr prepareVoxelsVolume(const Chunk& chunk); + std::shared_ptr prepareVoxelsVolume(const Chunk& chunk); + size_t enqueuedInFrame = 0; public: ChunksRenderer( const Level* level, @@ -71,13 +71,13 @@ public: virtual ~ChunksRenderer(); const Mesh* render( - const std::shared_ptr& chunk, bool important + const std::shared_ptr& chunk, bool important, bool lowPriority ); void unload(const Chunk* chunk); void clear(); const Mesh* getOrRender( - const std::shared_ptr& chunk, bool important + const std::shared_ptr& chunk, bool important, bool lowPriority ); void drawShadowsPass( diff --git a/src/graphics/render/commons.hpp b/src/graphics/render/commons.hpp index 5118f9c7d..41b352bac 100644 --- a/src/graphics/render/commons.hpp +++ b/src/graphics/render/commons.hpp @@ -1,5 +1,6 @@ #pragma once +#include "constants.hpp" #include "graphics/core/MeshData.hpp" #include "util/Buffer.hpp" @@ -51,3 +52,12 @@ struct ChunkMesh { SortingMeshData sortingMeshData; std::unique_ptr > sortedMesh; }; + +inline constexpr int VOXELS_BUFFER_PADDING = 2; + +template class StaticVoxelsVolume; + +using VoxelsRenderVolume = StaticVoxelsVolume< + CHUNK_W + VOXELS_BUFFER_PADDING * 2, + CHUNK_H, + CHUNK_D + VOXELS_BUFFER_PADDING * 2>; diff --git a/src/util/ObjectsPool.hpp b/src/util/ObjectsPool.hpp index 25f633ab1..45923a2c5 100644 --- a/src/util/ObjectsPool.hpp +++ b/src/util/ObjectsPool.hpp @@ -50,6 +50,10 @@ namespace util { size_t countTotal() const { return objects.size(); } + + size_t countFree() const { + return freeObjects.size(); + } private: std::vector> objects; std::queue freeObjects; diff --git a/src/util/ThreadPool.hpp b/src/util/ThreadPool.hpp index 4369d2856..198854a7d 100644 --- a/src/util/ThreadPool.hpp +++ b/src/util/ThreadPool.hpp @@ -52,7 +52,7 @@ namespace util { bool standaloneResults = true; bool stopOnFail = true; - void threadLoop(int index, std::shared_ptr> worker) { + void threadLoop(int index, std::unique_ptr> worker) { std::condition_variable variable; std::mutex mutex; bool locked = false; @@ -76,7 +76,7 @@ namespace util { { std::lock_guard lock(resultsMutex); results.push(ThreadPoolResult { - job, variable, index, locked, result}); + job, variable, index, locked, std::move(result)}); if (!standaloneResults) { locked = true; } @@ -115,7 +115,7 @@ namespace util { /// unlimited, -2 is half of auto count, -4 is quarter. ThreadPool( std::string name, - supplier>> workersSupplier, + supplier>> workersSupplier, consumer resultConsumer, int maxWorkers=UNLIMITED ) @@ -236,7 +236,7 @@ namespace util { return resultsProcessed; } - void enqueueJob(T job) { + void enqueueJob(T&& job) { { std::lock_guard lock(jobsMutex); jobs.push(std::move(job)); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index a4b693829..d835b26ba 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -335,26 +335,106 @@ bool Chunks::putChunk(const std::shared_ptr& chunk) { return false; } -// reduce nesting on next modification -// 25.06.2024: not now -// 11.11.2024: not now -// 12.12.2025: not now -void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const { - voxel* voxels = volume.getVoxels(); - light_t* lights = volume.getLights(); - int x = volume.getX(); - int y = volume.getY(); - int z = volume.getZ(); +static void fill_with_void( + voxel* voxels, + light_t* lights, + const glm::ivec3& pos, + const glm::ivec3& size, + int cx, + int cz +) { + for (int ly = pos.y; ly < pos.y + size.y; ly++) { + for (int lz = std::max(pos.z, cz * CHUNK_D); + lz < std::min(pos.z + size.z, (cz + 1) * CHUNK_D); + lz++) { + for (int lx = std::max(pos.x, cx * CHUNK_W); + lx < std::min(pos.x + size.x, (cx + 1) * CHUNK_W); + lx++) { + uint idx = vox_index( + lx - pos.x, ly - pos.y, lz - pos.z, size.x, size.z + ); + voxels[idx].id = BLOCK_VOID; + lights[idx] = 0; + } + } + } +} - int w = volume.getW(); - int h = std::min(volume.getH(), top); - int d = volume.getD(); +static inline light_t apply_backlight(light_t light) { + return Lightmap::combine( + std::min(15, Lightmap::extract(light, 0) + 1), + std::min(15, Lightmap::extract(light, 1) + 1), + std::min(15, Lightmap::extract(light, 2) + 1), + std::min(15, static_cast(Lightmap::extract(light, 3))) + ); +} - int scx = floordiv(x); - int scz = floordiv(z); +#include "util/timeutil.hpp" - int ecx = floordiv(x + w); - int ecz = floordiv(z + d); +// ugly +static inline void sample_chunk( + const decltype(ContentIndices::blocks)& defs, + const Chunk& chunk, + voxel* voxels, + light_t* lights, + const glm::ivec3& pos, + const glm::ivec3& size, + int cx, + int cz, + bool backlight +) { + const auto cvoxels = chunk.voxels; + const auto clights = chunk.lightmap ? chunk.lightmap->getLights() : nullptr; + for (int ly = pos.y; ly < pos.y + size.y; ly++) { + for (int lz = std::max(pos.z, cz * CHUNK_D); + lz < std::min(pos.z + size.z, (cz + 1) * CHUNK_D); + lz++) { + for (int lx = std::max(pos.x, cx * CHUNK_W); + lx < std::min(pos.x + size.x, (cx + 1) * CHUNK_W); + lx++) { + uint vidx = vox_index( + lx - pos.x, ly - pos.y, lz - pos.z, size.x, size.z + ); + uint cidx = vox_index( + lx - cx * CHUNK_W, + ly, + lz - cz * CHUNK_D, + CHUNK_W, + CHUNK_D + ); + auto& vox = voxels[vidx]; + vox = cvoxels[cidx]; + light_t light = clights ? clights[cidx] + : Lightmap::SUN_LIGHT_ONLY; + // todo: move to the BlocksRenderer + if (backlight) { + const auto block = defs.get(vox.id); + if (block && block->lightPassing) { + light = apply_backlight(light); + } + } + lights[vidx] = light; + } + } + } +} + +void Chunks::getVoxels( + voxel* voxels, + light_t* lights, + const glm::ivec3& pos, + const glm::ivec3& size, + bool backlight, + int top +) const { + timeutil::ScopeLogTimer log(111); + int h = std::min(size.y, top); + + int scx = floordiv(pos.x); + int scz = floordiv(pos.z); + + int ecx = floordiv(pos.x + size.x); + int ecz = floordiv(pos.z + size.z); int cw = ecx - scx + 1; int cd = ecz - scz + 1; @@ -364,67 +444,37 @@ void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const { for (int cx = scx; cx < scx + cw; cx++) { const auto chunk = getChunk(cx, cz); if (chunk == nullptr) { - // no chunk loaded -> filling with BLOCK_VOID - for (int ly = y; ly < y + h; ly++) { - for (int lz = std::max(z, cz * CHUNK_D); - lz < std::min(z + d, (cz + 1) * CHUNK_D); - lz++) { - for (int lx = std::max(x, cx * CHUNK_W); - lx < std::min(x + w, (cx + 1) * CHUNK_W); - lx++) { - uint idx = vox_index(lx - x, ly - y, lz - z, w, d); - voxels[idx].id = BLOCK_VOID; - lights[idx] = 0; - } - } - } - } else { - const voxel* cvoxels = chunk->voxels; - const light_t* clights = - chunk->lightmap ? chunk->lightmap->getLights() : nullptr; - for (int ly = y; ly < y + h; ly++) { - for (int lz = std::max(z, cz * CHUNK_D); - lz < std::min(z + d, (cz + 1) * CHUNK_D); - lz++) { - for (int lx = std::max(x, cx * CHUNK_W); - lx < std::min(x + w, (cx + 1) * CHUNK_W); - lx++) { - uint vidx = vox_index(lx - x, ly - y, lz - z, w, d); - uint cidx = vox_index( - lx - cx * CHUNK_W, - ly, - lz - cz * CHUNK_D, - CHUNK_W, - CHUNK_D - ); - voxels[vidx] = cvoxels[cidx]; - light_t light = clights ? clights[cidx] - : Lightmap::SUN_LIGHT_ONLY; - if (backlight) { - const auto block = - indices.blocks.get(voxels[vidx].id); - if (block && block->lightPassing) { - light = Lightmap::combine( - std::min(15, - Lightmap::extract(light, 0) + 1), - std::min(15, - Lightmap::extract(light, 1) + 1), - std::min(15, - Lightmap::extract(light, 2) + 1), - std::min(15, - static_cast(Lightmap::extract(light, 3))) - ); - } - } - lights[vidx] = light; - } - } - } + fill_with_void( + voxels, lights, pos, {size.x, h, size.z}, cx, cz + ); + continue; } + sample_chunk( + indices.blocks, + *chunk, + voxels, + lights, + pos, + {size.x, h, size.z}, + cx, + cz, + backlight + ); } } } +void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const { + getVoxels( + volume.getVoxels(), + volume.getLights(), + {volume.getX(), volume.getY(), volume.getZ()}, + {volume.getW(), volume.getH(), volume.getD()}, + backlight, + top + ); +} + void Chunks::saveAndClear() { areaMap.clear(); } diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index e185ce584..851ffb599 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -23,6 +23,8 @@ class LevelEvents; class Block; class VoxelsVolume; +template class StaticVoxelsVolume; + /// Player-centred chunks matrix class Chunks { LevelEvents* events; @@ -128,7 +130,34 @@ public: bool isReplaceableBlock(int32_t x, int32_t y, int32_t z); bool isObstacleBlock(int32_t x, int32_t y, int32_t z); - void getVoxels(VoxelsVolume& volume, bool backlight = false, int top = CHUNK_H) const; + void getVoxels( + VoxelsVolume& volume, bool backlight = false, int top = CHUNK_H + ) const; + + template + void getVoxels( + StaticVoxelsVolume& volume, + bool backlight = false, + int top = CHUNK_H + ) const { + getVoxels( + volume.getVoxels(), + volume.getLights(), + {volume.getX(), volume.getY(), volume.getZ()}, + {w, h, d}, + backlight, + top + ); + } + + void getVoxels( + voxel* voxels, + light_t* lights, + const glm::ivec3& pos, + const glm::ivec3& size, + bool backlight, + int top + ) const; void setCenter(int32_t x, int32_t z); void resize(uint32_t newW, uint32_t newD); diff --git a/src/voxels/VoxelsVolume.cpp b/src/voxels/VoxelsVolume.cpp deleted file mode 100644 index d74f69eef..000000000 --- a/src/voxels/VoxelsVolume.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "VoxelsVolume.hpp" - -VoxelsVolume::VoxelsVolume(int x, int y, int z, int w, int h, int d) - : x(x), - y(y), - z(z), - w(w), - h(h), - d(d), - voxels(std::make_unique(w * h * d)), - lights(std::make_unique(w * h * d)) { - for (int i = 0; i < w * h * d; i++) { - voxels[i].id = BLOCK_VOID; - } -} - -VoxelsVolume::VoxelsVolume(int w, int h, int d) - : VoxelsVolume(0, 0, 0, w, h, d) { -} - -VoxelsVolume::~VoxelsVolume() { -} - -void VoxelsVolume::setPosition(int x, int y, int z) { - this->x = x; - this->y = y; - this->z = z; -} diff --git a/src/voxels/VoxelsVolume.hpp b/src/voxels/VoxelsVolume.hpp index 72afc0786..bf57ae9e9 100644 --- a/src/voxels/VoxelsVolume.hpp +++ b/src/voxels/VoxelsVolume.hpp @@ -4,17 +4,25 @@ #include "typedefs.hpp" #include "voxel.hpp" -class VoxelsVolume { - int x, y, z; - int w, h, d; - std::unique_ptr voxels; - std::unique_ptr lights; -public: - VoxelsVolume(int w, int h, int d); - VoxelsVolume(int x, int y, int z, int w, int h, int d); - virtual ~VoxelsVolume(); +#include - void setPosition(int x, int y, int z); +class VoxelsVolume { +public: + static inline constexpr size_t MAX_VOXELS = CHUNK_VOL * 2; + + VoxelsVolume(int w, int h, int d) + : VoxelsVolume(0, 0, 0, w, h, d) {} + + VoxelsVolume(int x, int y, int z, int w, int h, int d) + : x(x), y(y), z(z), w(w), h(h), d(d) { + std::memset(voxels.get(), 0xFF, sizeof(voxel) * w * h * d); + } + + void setPosition(int x, int y, int z) { + this->x = x; + this->y = y; + this->z = z; + } int getX() const { return x; @@ -40,11 +48,11 @@ public: return d; } - voxel* getVoxels() const { + voxel* getVoxels() { return voxels.get(); } - light_t* getLights() const { + light_t* getLights() { return lights.get(); } @@ -72,4 +80,83 @@ public: } return lights[vox_index(bx - x, by - y, bz - z, w, d)]; } +private: + int x, y, z; + int w, h, d; + std::unique_ptr voxels; + std::unique_ptr lights; }; + + +template +class StaticVoxelsVolume { +public: + static inline constexpr size_t size = w * h * d; + static inline constexpr int width = w; + static inline constexpr int height = h; + static inline constexpr int depth = d; + + StaticVoxelsVolume() + : StaticVoxelsVolume(0, 0, 0) {} + + StaticVoxelsVolume(int x, int y, int z) + : x(x), y(y), z(z) { + std::memset(voxels, 0xFF, sizeof(voxel) * size); + } + + void setPosition(int x, int y, int z) { + this->x = x; + this->y = y; + this->z = z; + } + + int getX() const { + return x; + } + + int getY() const { + return y; + } + + int getZ() const { + return z; + } + + voxel* getVoxels() { + return voxels; + } + + light_t* getLights() { + return lights; + } + + inline blockid_t pickBlockId(int bx, int by, int bz) const { + if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || + bz >= z + d) { + return BLOCK_VOID; + } + return voxels[vox_index(bx - x, by - y, bz - z, w, d)].id; + } + + + inline voxel pickBlock(int bx, int by, int bz) const { + if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || + bz >= z + d) { + return {BLOCK_VOID, {}}; + } + return voxels[vox_index(bx - x, by - y, bz - z, w, d)]; + } + + inline light_t pickLight(int bx, int by, int bz) const { + if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || + bz >= z + d) { + return 0; + } + return lights[vox_index(bx - x, by - y, bz - z, w, d)]; + } +private: + int x, y, z; + voxel voxels[size]; + light_t lights[size]; +}; + diff --git a/src/world/files/WorldConverter.cpp b/src/world/files/WorldConverter.cpp index 431d4c41c..2f7716d3f 100644 --- a/src/world/files/WorldConverter.cpp +++ b/src/world/files/WorldConverter.cpp @@ -162,7 +162,7 @@ std::shared_ptr WorldConverter::startTask( } auto pool = std::make_shared>( "converter-pool", - [=]() { return std::make_shared(converter); }, + [=]() { return std::make_unique(converter); }, [=](int&&) {} ); auto& converterTasks = converter->tasks;