From 7c0c268508c9c6cd4061fb19d4d3e17a4ed18f82 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 9 Sep 2024 20:37:42 +0300 Subject: [PATCH] optimize AreaMap2D --- src/logic/BlocksController.cpp | 9 ++- src/logic/ChunksController.cpp | 22 +++--- src/util/AreaMap2D.hpp | 133 ++++++++++++++++++--------------- src/voxels/Chunks.cpp | 54 +++++++------ src/voxels/Chunks.hpp | 22 ++++-- src/world/Level.cpp | 2 +- 6 files changed, 131 insertions(+), 111 deletions(-) diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index 81cb592a..32802780 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -124,12 +124,13 @@ void BlocksController::randomTick( void BlocksController::randomTick(int tickid, int parts) { auto indices = level->content->getIndices(); - const auto& size = chunks->getSize(); + int width = chunks->getWidth(); + int height = chunks->getHeight(); int segments = 4; - for (uint z = padding; z < size.y - padding; z++) { - for (uint x = padding; x < size.x - padding; x++) { - int index = z * size.x + x; + for (uint z = padding; z < height - padding; z++) { + for (uint x = padding; x < width - padding; x++) { + int index = z * width + x; if ((index + tickid) % parts != 0) { continue; } diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index bd9e36c4..226acd48 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -52,14 +52,15 @@ void ChunksController::update(int64_t maxDuration) { } bool ChunksController::loadVisible() { - const auto& size = chunks->getSize(); + int sizeX = chunks->getWidth(); + int sizeY = chunks->getHeight(); int nearX = 0; int nearZ = 0; - int minDistance = ((size.x - padding * 2) / 2) * ((size.y - padding * 2) / 2); - for (uint z = padding; z < size.y - padding; z++) { - for (uint x = padding; x < size.x - padding; x++) { - int index = z * size.x + x; + int minDistance = ((sizeX - padding * 2) / 2) * ((sizeY - padding * 2) / 2); + for (uint z = padding; z < sizeY - padding; z++) { + for (uint x = padding; x < sizeX - padding; x++) { + int index = z * sizeX + x; auto& chunk = chunks->getChunks()[index]; if (chunk != nullptr) { if (chunk->flags.loaded && !chunk->flags.lighted) { @@ -69,8 +70,8 @@ bool ChunksController::loadVisible() { } continue; } - int lx = x - size.x / 2; - int lz = z - size.y / 2; + int lx = x - sizeX / 2; + int lz = z - sizeY / 2; int distance = (lx * lx + lz * lz); if (distance < minDistance) { minDistance = distance; @@ -80,12 +81,13 @@ bool ChunksController::loadVisible() { } } - const auto& chunk = chunks->getChunks()[nearZ * size.x + nearX]; + const auto& chunk = chunks->getChunks()[nearZ * sizeX + nearX]; if (chunk != nullptr) { return false; } - const auto& offset = chunks->getOffset(); - createChunk(nearX + offset.x, nearZ + offset.y); + int offsetX = chunks->getOffsetX(); + int offsetY = chunks->getOffsetY(); + createChunk(nearX + offsetX, nearZ + offsetY); return true; } diff --git a/src/util/AreaMap2D.hpp b/src/util/AreaMap2D.hpp index cbf90f5b..547b05b4 100644 --- a/src/util/AreaMap2D.hpp +++ b/src/util/AreaMap2D.hpp @@ -11,80 +11,81 @@ namespace util { template class AreaMap2D { - glm::vec<2, TCoord> offset; - glm::vec<2, TCoord> size; + TCoord offsetX, offsetY; + TCoord sizeX, sizeY; std::vector firstBuffer; std::vector secondBuffer; OutCallback outCallback; size_t valuesCount = 0; - void translate(const glm::vec<2, TCoord>& delta) { - if (delta.x == 0 && delta.y == 0) { + void translate(TCoord dx, TCoord dy) { + if (dx == 0 && dy == 0) { return; } std::fill(secondBuffer.begin(), secondBuffer.end(), T{}); - for (TCoord y = 0; y < size.y; y++) { - for (TCoord x = 0; x < size.x; x++) { - auto& value = firstBuffer[y * size.x + x]; - auto nx = x - delta.x; - auto ny = y - delta.y; + for (TCoord y = 0; y < sizeY; y++) { + for (TCoord x = 0; x < sizeX; x++) { + auto& value = firstBuffer[y * sizeX + x]; + auto nx = x - dx; + auto ny = y - dy; if (value == T{}) { continue; } - if (nx < 0 || ny < 0 || nx >= size.x || ny >= size.y) { + if (nx < 0 || ny < 0 || nx >= sizeX || ny >= sizeY) { if (outCallback) { outCallback(value); } valuesCount--; continue; } - secondBuffer[ny * size.x + nx] = value; + secondBuffer[ny * sizeX + nx] = value; } } std::swap(firstBuffer, secondBuffer); - offset += delta; + offsetX += dx; + offsetY += dy; } public: - AreaMap2D(glm::vec<2, TCoord> size) - : size(size), - firstBuffer(size.x * size.y), secondBuffer(size.x * size.y) { + AreaMap2D(TCoord width, TCoord height) + : sizeX(width), sizeY(height), + firstBuffer(width * height), secondBuffer(width * height) { } - const T* getIf(const glm::vec<2, TCoord>& pos) const { - auto localPos = pos - offset; - if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x || - localPos.y >= size.y) { + const T* getIf(TCoord x, TCoord y) const { + auto lx = x - offsetX; + auto ly = y - offsetY; + if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) { return nullptr; } - return &firstBuffer[localPos.y * size.x + localPos.x]; + return &firstBuffer[ly * sizeX + lx]; } - T get(const glm::vec<2, TCoord>& pos) { - auto localPos = pos - offset; - if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x || - localPos.y >= size.y) { + T get(TCoord x, TCoord y) { + auto lx = x - offsetX; + auto ly = y - offsetY; + if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) { return T{}; } - return firstBuffer[localPos.y * size.x + localPos.x]; + return firstBuffer[ly * sizeX + lx]; } - const T& require(const glm::vec<2, TCoord>& pos) const { - auto localPos = pos - offset; - if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x || - localPos.y >= size.y) { + const T& require(TCoord x, TCoord y) const { + auto lx = x - offsetX; + auto ly = y - offsetY; + if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) { throw std::invalid_argument("position is out of window"); } - return firstBuffer[localPos.y * size.x + localPos.x]; + return firstBuffer[ly * sizeX + lx]; } - bool set(const glm::vec<2, TCoord>& pos, T value) { - auto localPos = pos - offset; - if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x || - localPos.y >= size.y) { + bool set(TCoord x, TCoord y, T value) { + auto lx = x - offsetX; + auto ly = y - offsetY; + if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) { return false; } - auto& element = firstBuffer[localPos.y * size.x + localPos.x]; + auto& element = firstBuffer[ly * sizeX + lx]; if (!element) { valuesCount++; } @@ -96,41 +97,43 @@ namespace util { outCallback = callback; } - void resize(const glm::vec<2, TCoord>& newSize) { - if (newSize.x < size.x) { - TCoord delta = size.x - newSize.x; - translate({delta / 2, 0}); - translate({-delta, 0}); - translate({delta, 0}); + void resize(TCoord newSizeX, TCoord newSizeY) { + if (newSizeX < sizeX) { + TCoord delta = sizeX - newSizeX; + translate(delta / 2, 0); + translate(-delta, 0); + translate(delta, 0); } - if (newSize.y < size.y) { - TCoord delta = size.y - newSize.y; - translate({0, delta / 2}); - translate({0, -delta}); - translate({0, delta}); + if (newSizeY < sizeY) { + TCoord delta = sizeY - newSizeY; + translate(0, delta / 2); + translate(0, -delta); + translate(0, delta); } - const TCoord newVolume = newSize.x * newSize.y; + const TCoord newVolume = newSizeX * newSizeY; std::vector newFirstBuffer(newVolume); std::vector newSecondBuffer(newVolume); - for (TCoord y = 0; y < size.y && y < newSize.y; y++) { - for (TCoord x = 0; x < size.x && x < newSize.x; x++) { - newFirstBuffer[y * newSize.x + x] = firstBuffer[y * size.x + x]; + for (TCoord y = 0; y < sizeY && y < newSizeY; y++) { + for (TCoord x = 0; x < sizeX && x < newSizeX; x++) { + newFirstBuffer[y * newSizeX + x] = firstBuffer[y * sizeX + x]; } } - size = newSize; + sizeX = newSizeX; + sizeY = newSizeY; firstBuffer = std::move(newFirstBuffer); secondBuffer = std::move(newSecondBuffer); } - void setCenter(const glm::vec<2, TCoord>& center) { - auto delta = center - (offset + size / 2); - if (delta.x | delta.y) { - translate({delta.x, delta.y}); + void setCenter(TCoord centerX, TCoord centerY) { + auto deltaX = centerX - (offsetX + sizeX / 2); + auto deltaY = centerY - (offsetY + sizeY / 2); + if (deltaX | deltaY) { + translate(deltaX, deltaY); } } void clear() { - for (TCoord i = 0; i < size.x * size.y; i++) { + for (TCoord i = 0; i < sizeX * sizeY; i++) { auto value = firstBuffer[i]; firstBuffer[i] = {}; if (outCallback) { @@ -140,12 +143,20 @@ namespace util { valuesCount = 0; } - const glm::vec<2, TCoord>& getOffset() const { - return offset; + TCoord getOffsetX() const { + return offsetX; } - const glm::vec<2, TCoord>& getSize() const { - return size; + TCoord getOffsetY() const { + return offsetY; + } + + TCoord getWidth() const { + return sizeX; + } + + TCoord getHeight() const { + return sizeX; } const std::vector& getBuffer() const { @@ -157,7 +168,7 @@ namespace util { } TCoord area() const { - return size.x * size.y; + return sizeX * sizeY; } }; } diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index be5c3d25..ae8eee1a 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -23,8 +23,8 @@ #include "voxel.hpp" Chunks::Chunks( - uint32_t w, - uint32_t d, + int32_t w, + int32_t d, int32_t ox, int32_t oz, WorldFiles* wfile, @@ -32,9 +32,9 @@ Chunks::Chunks( ) : level(level), indices(level->content->getIndices()), - areaMap({w, d}), + areaMap(w, d), worldFiles(wfile) { - areaMap.setCenter({ox-w/2, oz-d/2}); + areaMap.setCenter(ox-w/2, oz-d/2); areaMap.setOutCallback([this](const auto& chunk) { save(chunk.get()); }); @@ -46,7 +46,7 @@ voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const { } int cx = floordiv(x, CHUNK_W); int cz = floordiv(z, CHUNK_D); - auto ptr = areaMap.getIf({cx, cz}); + auto ptr = areaMap.getIf(cx, cz); if (ptr == nullptr) { return nullptr; } @@ -83,8 +83,8 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z) { def.rotatable ? def.rt.hitboxes[v->state.rotation] : def.hitboxes; for (const auto& hitbox : boxes) { if (hitbox.contains( - {x - ix - offset.x, y - iy - offset.y, z - iz - offset.z} - )) { + {x - ix - offset.x, y - iy - offset.y, z - iz - offset.z} + )) { return &hitbox; } } @@ -117,7 +117,7 @@ ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) { int cx = floordiv(x, CHUNK_W); int cz = floordiv(z, CHUNK_D); - auto ptr = areaMap.getIf({cx, cz}); + auto ptr = areaMap.getIf(cx, cz); if (ptr == nullptr) { return 0; } @@ -137,7 +137,7 @@ light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) { int cx = floordiv(x, CHUNK_W); int cz = floordiv(z, CHUNK_D); - auto ptr = areaMap.getIf({cx, cz}); + auto ptr = areaMap.getIf(cx, cz); if (ptr == nullptr) { return 0; } @@ -156,14 +156,14 @@ Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z) { } int cx = floordiv(x, CHUNK_W); int cz = floordiv(z, CHUNK_D); - if (auto ptr = areaMap.getIf({cx, cz})) { + if (auto ptr = areaMap.getIf(cx, cz)) { return ptr->get(); } return nullptr; } Chunk* Chunks::getChunk(int x, int z) { - if (auto ptr = areaMap.getIf({x, z})) { + if (auto ptr = areaMap.getIf(x, z)) { return ptr->get(); } return nullptr; @@ -351,11 +351,9 @@ void Chunks::set( if (y < 0 || y >= CHUNK_H) { return; } - int32_t gx = x; - int32_t gz = z; int cx = floordiv(x, CHUNK_W); int cz = floordiv(z, CHUNK_D); - auto ptr = areaMap.getIf({cx, cz}); + auto ptr = areaMap.getIf(cx, cz); if (ptr == nullptr) { return; } @@ -373,7 +371,7 @@ void Chunks::set( chunk->removeBlockInventory(lx, y, lz); } if (prevdef.rt.extended && !vox.state.segment) { - eraseSegments(prevdef, vox.state, gx, y, gz); + eraseSegments(prevdef, vox.state, x, y, z); } // block initialization @@ -382,7 +380,7 @@ void Chunks::set( vox.state = state; chunk->setModifiedAndUnsaved(); if (!state.segment && newdef.rt.extended) { - repairSegments(newdef, state, gx, y, gz); + repairSegments(newdef, state, x, y, z); } if (y < chunk->bottom) @@ -424,9 +422,9 @@ voxel* Chunks::rayCast( float dz = dir.z; float t = 0.0f; - int ix = floor(px); - int iy = floor(py); - int iz = floor(pz); + int ix = std::floor(px); + int iy = std::floor(py); + int iz = std::floor(pz); int stepx = (dx > 0.0f) ? 1 : -1; int stepy = (dy > 0.0f) ? 1 : -1; @@ -434,9 +432,9 @@ voxel* Chunks::rayCast( constexpr float infinity = std::numeric_limits::infinity(); constexpr float epsilon = 1e-6f; // 0.000001 - float txDelta = (fabs(dx) < epsilon) ? infinity : abs(1.0f / dx); - float tyDelta = (fabs(dy) < epsilon) ? infinity : abs(1.0f / dy); - float tzDelta = (fabs(dz) < epsilon) ? infinity : abs(1.0f / dz); + float txDelta = (std::fabs(dx) < epsilon) ? infinity : std::fabs(1.0f / dx); + float tyDelta = (std::fabs(dy) < epsilon) ? infinity : std::fabs(1.0f / dy); + float tzDelta = (std::fabs(dz) < epsilon) ? infinity : std::fabs(1.0f / dz); float xdist = (stepx > 0) ? (ix + 1 - px) : (px - ix); float ydist = (stepy > 0) ? (iy + 1 - py) : (py - iy); @@ -567,9 +565,9 @@ glm::vec3 Chunks::rayCastToObstacle( constexpr float infinity = std::numeric_limits::infinity(); constexpr float epsilon = 1e-6f; // 0.000001 - float txDelta = (fabs(dx) < epsilon) ? infinity : abs(1.0f / dx); - float tyDelta = (fabs(dy) < epsilon) ? infinity : abs(1.0f / dy); - float tzDelta = (fabs(dz) < epsilon) ? infinity : abs(1.0f / dz); + float txDelta = (std::fabs(dx) < epsilon) ? infinity : std::fabs(1.0f / dx); + float tyDelta = (std::fabs(dy) < epsilon) ? infinity : std::fabs(1.0f / dy); + float tzDelta = (std::fabs(dz) < epsilon) ? infinity : std::fabs(1.0f / dz); float xdist = (stepx > 0) ? (ix + 1 - px) : (px - ix); float ydist = (stepy > 0) ? (iy + 1 - py) : (py - iy); @@ -642,15 +640,15 @@ glm::vec3 Chunks::rayCastToObstacle( } void Chunks::setCenter(int32_t x, int32_t z) { - areaMap.setCenter({floordiv(x, CHUNK_W), floordiv(z, CHUNK_D)}); + areaMap.setCenter(floordiv(x, CHUNK_W), floordiv(z, CHUNK_D)); } void Chunks::resize(uint32_t newW, uint32_t newD) { - areaMap.resize({newW, newD}); + areaMap.resize(newW, newD); } bool Chunks::putChunk(const std::shared_ptr& chunk) { - return areaMap.set({chunk->x, chunk->z}, chunk); + return areaMap.set(chunk->x, chunk->z, chunk); } void Chunks::saveAndClear() { diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index 5214f81e..6e73193a 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -35,14 +35,14 @@ class Chunks { const Block& def, blockstate state, glm::ivec3 origin, uint8_t rotation ); - util::AreaMap2D> areaMap; + util::AreaMap2D, int32_t> areaMap; public: size_t visible = 0; WorldFiles* worldFiles; Chunks( - uint32_t w, - uint32_t d, + int32_t w, + int32_t d, int32_t ox, int32_t oz, WorldFiles* worldFiles, @@ -113,12 +113,20 @@ public: return areaMap.getBuffer(); } - const glm::ivec2& getSize() const { - return areaMap.getSize(); + int getWidth() const { + return areaMap.getWidth(); } - const glm::ivec2& getOffset() const { - return areaMap.getOffset(); + int getHeight() const { + return areaMap.getHeight(); + } + + int getOffsetX() const { + return areaMap.getOffsetX(); + } + + int getOffsetY() const { + return areaMap.getOffsetY(); } size_t getChunksCount() const { diff --git a/src/world/Level.cpp b/src/world/Level.cpp index 190559d7..39384b4a 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -86,7 +86,7 @@ void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) { (settings.chunks.loadDistance.get() + settings.chunks.padding.get()) * 2LL ); - if (chunks->getSize().x != diameter) { + if (chunks->getWidth() != diameter) { chunks->resize(diameter, diameter); } }