forked from Mirrorlandia_minetest/minetest
Implement mapblock camera offset correctly (#10702)
Implement mapblock camera offset correctly - reduce client jitter Co-authored-by: hecktest <>
This commit is contained in:
parent
07e0b527cf
commit
6d7067fd37
@ -31,6 +31,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "client/renderingengine.h"
|
#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(
|
ClientMap::ClientMap(
|
||||||
Client *client,
|
Client *client,
|
||||||
MapDrawControl &control,
|
MapDrawControl &control,
|
||||||
@ -182,9 +213,7 @@ void ClientMap::updateDrawList()
|
|||||||
if not seen on display
|
if not seen on display
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (block->mesh) {
|
if (!block->mesh) {
|
||||||
block->mesh->updateCameraOffset(m_camera_offset);
|
|
||||||
} else {
|
|
||||||
// Ignore if mesh doesn't exist
|
// Ignore if mesh doesn't exist
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -229,50 +258,6 @@ void ClientMap::updateDrawList()
|
|||||||
g_profiler->avg("MapBlocks loaded [#]", blocks_loaded);
|
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)
|
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
{
|
{
|
||||||
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
||||||
@ -317,6 +302,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
MeshBufListList drawbufs;
|
MeshBufListList drawbufs;
|
||||||
|
|
||||||
for (auto &i : m_drawlist) {
|
for (auto &i : m_drawlist) {
|
||||||
|
v3s16 block_pos = i.first;
|
||||||
MapBlock *block = i.second;
|
MapBlock *block = i.second;
|
||||||
|
|
||||||
// If the mesh of the block happened to get deleted, ignore it
|
// 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,
|
material.setFlag(video::EMF_WIREFRAME,
|
||||||
m_control.show_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");
|
TimeTaker draw("Drawing mesh buffers");
|
||||||
|
|
||||||
|
core::matrix4 m; // Model matrix
|
||||||
|
v3f offset = intToFloat(m_camera_offset, BS);
|
||||||
|
|
||||||
// Render all layers in order
|
// Render all layers in order
|
||||||
for (auto &lists : drawbufs.lists) {
|
for (auto &lists : drawbufs.lists) {
|
||||||
for (MeshBufList &list : lists) {
|
for (MeshBufList &list : lists) {
|
||||||
@ -402,7 +391,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
driver->setMaterial(list.m);
|
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);
|
driver->drawMeshBuffer(buf);
|
||||||
vertex_count += buf->getVertexCount();
|
vertex_count += buf->getVertexCount();
|
||||||
}
|
}
|
||||||
@ -607,5 +602,3 @@ void ClientMap::PrintInfo(std::ostream &out)
|
|||||||
{
|
{
|
||||||
out<<"ClientMap: ";
|
out<<"ClientMap: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,25 @@ struct MapDrawControl
|
|||||||
bool show_wireframe = false;
|
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 Client;
|
||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
|
|
||||||
|
@ -1175,13 +1175,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
|
|||||||
buf->drop();
|
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 (m_mesh[layer]) {
|
||||||
#if 0
|
#if 0
|
||||||
// Usually 1-700 faces and 1-7 materials
|
// Usually 1-700 faces and 1-7 materials
|
||||||
@ -1308,19 +1301,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
|||||||
return true;
|
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)
|
video::SColor encode_light(u16 light, u8 emissive_light)
|
||||||
{
|
{
|
||||||
// Get components
|
// Get components
|
||||||
|
@ -160,9 +160,6 @@ private:
|
|||||||
// of sunlit vertices
|
// of sunlit vertices
|
||||||
// Keys are pairs of (mesh index, buffer index in the mesh)
|
// 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;
|
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
Reference in New Issue
Block a user