Skip to content

Commit

Permalink
Implement mapblock camera offset correctly (#10702)
Browse files Browse the repository at this point in the history
Implement mapblock camera offset correctly - reduce client jitter

Co-authored-by: hecktest <>
  • Loading branch information
hecktest committed Dec 5, 2020
1 parent 07e0b52 commit 6d7067f
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 74 deletions.
95 changes: 44 additions & 51 deletions src/client/clientmap.cpp
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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) {
Expand All @@ -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();
}
Expand Down Expand Up @@ -607,5 +602,3 @@ void ClientMap::PrintInfo(std::ostream &out)
{
out<<"ClientMap: ";
}


19 changes: 19 additions & 0 deletions src/client/clientmap.h
Expand Up @@ -35,6 +35,25 @@ struct MapDrawControl
bool show_wireframe = false;
};

struct MeshBufList
{
video::SMaterial m;
std::vector<std::pair<v3s16,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();
void add(scene::IMeshBuffer *buf, v3s16 position, u8 layer);
};

class Client;
class ITextureSource;

Expand Down
20 changes: 0 additions & 20 deletions src/client/mapblock_mesh.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions src/client/mapblock_mesh.h
Expand Up @@ -160,9 +160,6 @@ class MapBlockMesh
// of sunlit vertices
// Keys are pairs of (mesh index, buffer index in the mesh)
std::map<std::pair<u8, u32>, std::map<u32, video::SColor > > m_daynight_diffs;

// Camera offset info -> do we have to translate the mesh?
v3s16 m_camera_offset;
};

/*!
Expand Down

0 comments on commit 6d7067f

Please sign in to comment.