From 6d7067fd37a8084aca139ecab552982e0ee99582 Mon Sep 17 00:00:00 2001 From: hecks <42101236+hecktest@users.noreply.github.com> Date: Sun, 6 Dec 2020 00:03:40 +0100 Subject: [PATCH] Implement mapblock camera offset correctly (#10702) Implement mapblock camera offset correctly - reduce client jitter Co-authored-by: hecktest <> --- src/client/clientmap.cpp | 95 +++++++++++++++++------------------- src/client/clientmap.h | 19 ++++++++ src/client/mapblock_mesh.cpp | 20 -------- src/client/mapblock_mesh.h | 3 -- 4 files changed, 63 insertions(+), 74 deletions(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 09072858a..fa47df3f4 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -31,6 +31,37 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "client/renderingengine.h" +// struct MeshBufListList +void MeshBufListList::clear() +{ + for (auto &list : lists) + list.clear(); +} + +void MeshBufListList::add(scene::IMeshBuffer *buf, v3s16 position, u8 layer) +{ + // Append to the correct layer + std::vector &list = lists[layer]; + const video::SMaterial &m = buf->getMaterial(); + for (MeshBufList &l : list) { + // comparing a full material is quite expensive so we don't do it if + // not even first texture is equal + if (l.m.TextureLayer[0].Texture != m.TextureLayer[0].Texture) + continue; + + if (l.m == m) { + l.bufs.emplace_back(position, buf); + return; + } + } + MeshBufList l; + l.m = m; + l.bufs.emplace_back(position, buf); + list.emplace_back(l); +} + +// ClientMap + ClientMap::ClientMap( Client *client, MapDrawControl &control, @@ -182,9 +213,7 @@ void ClientMap::updateDrawList() if not seen on display */ - if (block->mesh) { - block->mesh->updateCameraOffset(m_camera_offset); - } else { + if (!block->mesh) { // Ignore if mesh doesn't exist continue; } @@ -229,50 +258,6 @@ void ClientMap::updateDrawList() g_profiler->avg("MapBlocks loaded [#]", blocks_loaded); } -struct MeshBufList -{ - video::SMaterial m; - std::vector bufs; -}; - -struct MeshBufListList -{ - /*! - * Stores the mesh buffers of the world. - * The array index is the material's layer. - * The vector part groups vertices by material. - */ - std::vector lists[MAX_TILE_LAYERS]; - - void clear() - { - for (auto &list : lists) - list.clear(); - } - - void add(scene::IMeshBuffer *buf, u8 layer) - { - // Append to the correct layer - std::vector &list = lists[layer]; - const video::SMaterial &m = buf->getMaterial(); - for (MeshBufList &l : list) { - // comparing a full material is quite expensive so we don't do it if - // not even first texture is equal - if (l.m.TextureLayer[0].Texture != m.TextureLayer[0].Texture) - continue; - - if (l.m == m) { - l.bufs.push_back(buf); - return; - } - } - MeshBufList l; - l.m = m; - l.bufs.push_back(buf); - list.push_back(l); - } -}; - void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) { bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT; @@ -317,6 +302,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) MeshBufListList drawbufs; for (auto &i : m_drawlist) { + v3s16 block_pos = i.first; MapBlock *block = i.second; // If the mesh of the block happened to get deleted, ignore it @@ -382,7 +368,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) material.setFlag(video::EMF_WIREFRAME, m_control.show_wireframe); - drawbufs.add(buf, layer); + drawbufs.add(buf, block_pos, layer); } } } @@ -391,6 +377,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) TimeTaker draw("Drawing mesh buffers"); + core::matrix4 m; // Model matrix + v3f offset = intToFloat(m_camera_offset, BS); + // Render all layers in order for (auto &lists : drawbufs.lists) { for (MeshBufList &list : lists) { @@ -402,7 +391,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) } driver->setMaterial(list.m); - for (scene::IMeshBuffer *buf : list.bufs) { + for (auto &pair : list.bufs) { + scene::IMeshBuffer *buf = pair.second; + + v3f block_wpos = intToFloat(pair.first * MAP_BLOCKSIZE, BS); + m.setTranslation(block_wpos - offset); + + driver->setTransform(video::ETS_WORLD, m); driver->drawMeshBuffer(buf); vertex_count += buf->getVertexCount(); } @@ -607,5 +602,3 @@ void ClientMap::PrintInfo(std::ostream &out) { out<<"ClientMap: "; } - - diff --git a/src/client/clientmap.h b/src/client/clientmap.h index 172e3a1d6..57cc4427e 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -35,6 +35,25 @@ struct MapDrawControl bool show_wireframe = false; }; +struct MeshBufList +{ + video::SMaterial m; + std::vector> bufs; +}; + +struct MeshBufListList +{ + /*! + * Stores the mesh buffers of the world. + * The array index is the material's layer. + * The vector part groups vertices by material. + */ + std::vector lists[MAX_TILE_LAYERS]; + + void clear(); + void add(scene::IMeshBuffer *buf, v3s16 position, u8 layer); +}; + class Client; class ITextureSource; diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index 6a59fabe3..dac25a066 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -1175,13 +1175,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): buf->drop(); } - /* - Do some stuff to the mesh - */ - m_camera_offset = camera_offset; - translateMesh(m_mesh[layer], - intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS)); - if (m_mesh[layer]) { #if 0 // Usually 1-700 faces and 1-7 materials @@ -1308,19 +1301,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, return true; } -void MapBlockMesh::updateCameraOffset(v3s16 camera_offset) -{ - if (camera_offset != m_camera_offset) { - for (scene::IMesh *layer : m_mesh) { - translateMesh(layer, - intToFloat(m_camera_offset - camera_offset, BS)); - if (m_enable_vbo) - layer->setDirty(); - } - m_camera_offset = camera_offset; - } -} - video::SColor encode_light(u16 light, u8 emissive_light) { // Get components diff --git a/src/client/mapblock_mesh.h b/src/client/mapblock_mesh.h index 6a9c00ed5..0308b8161 100644 --- a/src/client/mapblock_mesh.h +++ b/src/client/mapblock_mesh.h @@ -160,9 +160,6 @@ private: // of sunlit vertices // Keys are pairs of (mesh index, buffer index in the mesh) std::map, std::map > m_daynight_diffs; - - // Camera offset info -> do we have to translate the mesh? - v3s16 m_camera_offset; }; /*!