]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/client/clientmap.cpp
Implement mapblock camera offset correctly (#10702)
[dragonfireclient.git] / src / client / clientmap.cpp
index 09072858a8e984978552616e7a1f0de3633a1989..fa47df3f4bbf51716f7b92fc4c3aa195f6bd55d3 100644 (file)
@@ -31,6 +31,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <algorithm>
 #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<MeshBufList> &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<scene::IMeshBuffer*> 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<MeshBufList> 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<MeshBufList> &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: ";
 }
-
-