forked from Mirrorlandia_minetest/minetest
Replace clientmap's MeshBufListList with a hashmap
This commit is contained in:
parent
a22b1700a4
commit
3eab5e9002
@ -34,33 +34,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
// struct MeshBufListList
|
namespace {
|
||||||
void MeshBufListList::clear()
|
// A helper struct
|
||||||
{
|
struct MeshBufListMaps
|
||||||
for (auto &list : lists)
|
{
|
||||||
list.clear();
|
struct MaterialHash
|
||||||
}
|
{
|
||||||
|
size_t operator()(const video::SMaterial &m) const noexcept
|
||||||
|
{
|
||||||
|
// Only hash first texture. Simple and fast.
|
||||||
|
return std::hash<video::ITexture *>{}(m.TextureLayers[0].Texture);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using MeshBufListMap = std::unordered_map<
|
||||||
|
video::SMaterial,
|
||||||
|
std::vector<std::pair<v3s16, scene::IMeshBuffer *>>,
|
||||||
|
MaterialHash>;
|
||||||
|
|
||||||
|
std::array<MeshBufListMap, MAX_TILE_LAYERS> maps;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for (auto &map : maps)
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(scene::IMeshBuffer *buf, v3s16 position, u8 layer)
|
||||||
|
{
|
||||||
|
assert(layer < MAX_TILE_LAYERS);
|
||||||
|
|
||||||
void MeshBufListList::add(scene::IMeshBuffer *buf, v3s16 position, u8 layer)
|
|
||||||
{
|
|
||||||
// Append to the correct layer
|
// Append to the correct layer
|
||||||
std::vector<MeshBufList> &list = lists[layer];
|
auto &map = maps[layer];
|
||||||
const video::SMaterial &m = buf->getMaterial();
|
const video::SMaterial &m = buf->getMaterial();
|
||||||
for (MeshBufList &l : list) {
|
auto &bufs = map[m]; // default constructs if non-existent
|
||||||
// comparing a full material is quite expensive so we don't do it if
|
bufs.emplace_back(position, buf);
|
||||||
// not even first texture is equal
|
|
||||||
if (l.m.TextureLayers[0].Texture != m.TextureLayers[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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_settings_changed(const std::string &name, void *data)
|
static void on_settings_changed(const std::string &name, void *data)
|
||||||
@ -737,7 +747,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
Draw the selected MapBlocks
|
Draw the selected MapBlocks
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MeshBufListList grouped_buffers;
|
MeshBufListMaps grouped_buffers;
|
||||||
std::vector<DrawDescriptor> draw_order;
|
std::vector<DrawDescriptor> draw_order;
|
||||||
video::SMaterial previous_material;
|
video::SMaterial previous_material;
|
||||||
|
|
||||||
@ -793,7 +803,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// otherwise, group buffers across meshes
|
// otherwise, group buffers across meshes
|
||||||
// using MeshBufListList
|
// using MeshBufListMaps
|
||||||
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
||||||
scene::IMesh *mesh = block_mesh->getMesh(layer);
|
scene::IMesh *mesh = block_mesh->getMesh(layer);
|
||||||
assert(mesh);
|
assert(mesh);
|
||||||
@ -819,11 +829,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Capture draw order for all solid meshes
|
// Capture draw order for all solid meshes
|
||||||
for (auto &lists : grouped_buffers.lists) {
|
for (auto &map : grouped_buffers.maps) {
|
||||||
for (MeshBufList &list : lists) {
|
for (auto &list : map) {
|
||||||
// iterate in reverse to draw closest blocks first
|
// iterate in reverse to draw closest blocks first
|
||||||
for (auto it = list.bufs.rbegin(); it != list.bufs.rend(); ++it) {
|
for (auto it = list.second.rbegin(); it != list.second.rend(); ++it) {
|
||||||
draw_order.emplace_back(it->first, it->second, it != list.bufs.rbegin());
|
draw_order.emplace_back(it->first, it->second, it != list.second.rbegin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1103,7 +1113,7 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
|
|||||||
u32 drawcall_count = 0;
|
u32 drawcall_count = 0;
|
||||||
u32 vertex_count = 0;
|
u32 vertex_count = 0;
|
||||||
|
|
||||||
MeshBufListList grouped_buffers;
|
MeshBufListMaps grouped_buffers;
|
||||||
std::vector<DrawDescriptor> draw_order;
|
std::vector<DrawDescriptor> draw_order;
|
||||||
|
|
||||||
|
|
||||||
@ -1144,7 +1154,7 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// otherwise, group buffers across meshes
|
// otherwise, group buffers across meshes
|
||||||
// using MeshBufListList
|
// using MeshBufListMaps
|
||||||
MapBlockMesh *mapBlockMesh = block->mesh;
|
MapBlockMesh *mapBlockMesh = block->mesh;
|
||||||
assert(mapBlockMesh);
|
assert(mapBlockMesh);
|
||||||
|
|
||||||
@ -1167,18 +1177,18 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 buffer_count = 0;
|
u32 buffer_count = 0;
|
||||||
for (auto &lists : grouped_buffers.lists)
|
for (auto &map : grouped_buffers.maps)
|
||||||
for (MeshBufList &list : lists)
|
for (auto &list : map)
|
||||||
buffer_count += list.bufs.size();
|
buffer_count += list.second.size();
|
||||||
|
|
||||||
draw_order.reserve(draw_order.size() + buffer_count);
|
draw_order.reserve(draw_order.size() + buffer_count);
|
||||||
|
|
||||||
// Capture draw order for all solid meshes
|
// Capture draw order for all solid meshes
|
||||||
for (auto &lists : grouped_buffers.lists) {
|
for (auto &map : grouped_buffers.maps) {
|
||||||
for (MeshBufList &list : lists) {
|
for (auto &list : map) {
|
||||||
// iterate in reverse to draw closest blocks first
|
// iterate in reverse to draw closest blocks first
|
||||||
for (auto it = list.bufs.rbegin(); it != list.bufs.rend(); ++it)
|
for (auto it = list.second.rbegin(); it != list.second.rend(); ++it)
|
||||||
draw_order.emplace_back(it->first, it->second, it != list.bufs.rbegin());
|
draw_order.emplace_back(it->first, it->second, it != list.second.rbegin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,25 +37,6 @@ 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;
|
||||||
class PartialMeshBuffer;
|
class PartialMeshBuffer;
|
||||||
|
Loading…
Reference in New Issue
Block a user