diff options
author | x2048 <codeforsmile@gmail.com> | 2023-01-31 17:30:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-31 17:30:59 +0100 |
commit | 69fc20610947610b7829f3bfad82e23ed705b764 (patch) | |
tree | 775cb27a4875a071fccddee87b80730e39ed9b14 /src/client/mesh_generator_thread.cpp | |
parent | cded6a3945206e51c35adbd063f1aec3a47e310f (diff) | |
download | minetest-69fc20610947610b7829f3bfad82e23ed705b764.tar.xz |
8x block meshes (#13133)
Reduce the number of drawcalls by generating a mesh per 8 blocks (2x2x2). Only blocks with even coordinates (lowest bit set to 0) will get a mesh.
Note: This also removes the old 'loops' algorithm for building the draw list, because it produces visual artifacts and cannot be made compatible with the approach of having a mesh for every 8th block without hurting performance.
Co-authored-by: Jude Melton-Houghton <jwmhjwmh@gmail.com>
Co-authored-by: Lars <larsh@apache.org>
Co-authored-by: sfan5 <sfan5@live.de>
Diffstat (limited to 'src/client/mesh_generator_thread.cpp')
-rw-r--r-- | src/client/mesh_generator_thread.cpp | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/src/client/mesh_generator_thread.cpp b/src/client/mesh_generator_thread.cpp index adea057d6..6d1fe2bda 100644 --- a/src/client/mesh_generator_thread.cpp +++ b/src/client/mesh_generator_thread.cpp @@ -25,6 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "util/directiontables.h" +static class BlockPlaceholder { +public: + MapNode data[MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE]; + + BlockPlaceholder() + { + for (std::size_t i = 0; i < MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; i++) + data[i] = MapNode(CONTENT_IGNORE); + } + +} block_placeholder; /* QueuedMeshUpdate */ @@ -66,28 +77,31 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool MutexAutoLock lock(m_mutex); + // Mesh is placed at even positions at all coordinates + // (every 8-th block) and will cover 8 blocks + v3s16 mesh_position(p.X & ~1, p.Y & ~1, p.Z & ~1); /* Mark the block as urgent if requested */ if (urgent) - m_urgents.insert(p); + m_urgents.insert(mesh_position); /* Find if block is already in queue. If it is, update the data and quit. */ for (QueuedMeshUpdate *q : m_queue) { - if (q->p == p) { + if (q->p == mesh_position) { // NOTE: We are not adding a new position to the queue, thus // refcount_from_queue stays the same. if(ack_block_to_server) - q->ack_block_to_server = true; + q->ack_list.push_back(p); q->crack_level = m_client->getCrackLevel(); q->crack_pos = m_client->getCrackPos(); q->urgent |= urgent; - for (std::size_t i = 1; i < q->map_blocks.size(); i++) { + for (std::size_t i = 0; i < q->map_blocks.size(); i++) { if (!q->map_blocks[i]) { - MapBlock *block = map->getBlockNoCreateNoEx(q->p + g_26dirs[i - 1]); + MapBlock *block = map->getBlockNoCreateNoEx(q->p + g_64dirs[i]); if (block) { block->refGrab(); q->map_blocks[i] = block; @@ -99,16 +113,13 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool } /* - Cache the block data (force-update the center block, don't update the - neighbors but get them if they aren't already cached) + Make a list of blocks necessary for mesh generation and lock the blocks in memory. */ - std::vector<MapBlock *> cached_blocks; - cached_blocks.reserve(3*3*3); - cached_blocks.push_back(main_block); - main_block->refGrab(); - for (v3s16 dp : g_26dirs) { - MapBlock *block = map->getBlockNoCreateNoEx(p + dp); - cached_blocks.push_back(block); + std::vector<MapBlock *> map_blocks; + map_blocks.reserve(4*4*4); + for (v3s16 dp : g_64dirs) { + MapBlock *block = map->getBlockNoCreateNoEx(mesh_position + dp); + map_blocks.push_back(block); if (block) block->refGrab(); } @@ -117,12 +128,13 @@ bool MeshUpdateQueue::addBlock(Map *map, v3s16 p, bool ack_block_to_server, bool Add the block */ QueuedMeshUpdate *q = new QueuedMeshUpdate; - q->p = p; - q->ack_block_to_server = ack_block_to_server; + q->p = mesh_position; + if(ack_block_to_server) + q->ack_list.push_back(p); q->crack_level = m_client->getCrackLevel(); q->crack_pos = m_client->getCrackPos(); q->urgent = urgent; - q->map_blocks = std::move(cached_blocks); + q->map_blocks = std::move(map_blocks); m_queue.push_back(q); return true; @@ -170,12 +182,14 @@ void MeshUpdateQueue::fillDataFromMapBlocks(QueuedMeshUpdate *q) { MeshMakeData *data = new MeshMakeData(m_client, m_cache_enable_shaders); q->data = data; + data->side_length = 2 * MAP_BLOCKSIZE; data->fillBlockDataBegin(q->p); - for (MapBlock *block : q->map_blocks) - if (block) - data->fillBlockData(block->getPos() - q->p, block->getData()); + for (std::size_t i = 0; i < 64; i++) { + MapBlock *block = q->map_blocks[i]; + data->fillBlockData(g_64dirs[i], block ? block->getData() : block_placeholder.data); + } data->setCrack(q->crack_level, q->crack_pos); data->setSmoothLighting(m_cache_smooth_lighting); @@ -208,7 +222,7 @@ void MeshUpdateWorkerThread::doUpdate() r.p = q->p; r.mesh = mesh_new; r.solid_sides = get_solid_sides(q->data); - r.ack_block_to_server = q->ack_block_to_server; + r.ack_list = std::move(q->ack_list); r.urgent = q->urgent; r.map_blocks = q->map_blocks; |