aboutsummaryrefslogtreecommitdiff
path: root/src/client/clientmap.cpp
diff options
context:
space:
mode:
authorDS <vorunbekannt75@web.de>2022-09-18 15:28:53 +0200
committerGitHub <noreply@github.com>2022-09-18 15:28:53 +0200
commitc9ed059d9170f2f7f662cbb59e6009fd54c8ed3f (patch)
tree99b6adee12a0e76b3f2a25e2a6e5975bfaeaac28 /src/client/clientmap.cpp
parenta428a0cf37581a35f9c4f81c2e71633e6cc3dbb9 (diff)
downloadminetest-c9ed059d9170f2f7f662cbb59e6009fd54c8ed3f.tar.xz
Client map: do frustum culling via planes (#12710)
Diffstat (limited to 'src/client/clientmap.cpp')
-rw-r--r--src/client/clientmap.cpp67
1 files changed, 35 insertions, 32 deletions
diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp
index 669c673aa..23234c365 100644
--- a/src/client/clientmap.cpp
+++ b/src/client/clientmap.cpp
@@ -196,22 +196,12 @@ void ClientMap::updateDrawList()
}
m_drawlist.clear();
- const v3f camera_position = m_camera_position;
- const v3f camera_direction = m_camera_direction;
-
- // Use a higher fov to accomodate faster camera movements.
- // Blocks are cropped better when they are drawn.
- const f32 camera_fov = m_camera_fov * 1.1f;
-
- v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
+ v3s16 cam_pos_nodes = floatToInt(m_camera_position, BS);
v3s16 p_blocks_min;
v3s16 p_blocks_max;
getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);
- // Read the vision range, unless unlimited range is enabled.
- float range = m_control.range_all ? 1e7 : m_control.wanted_range;
-
// Number of blocks currently loaded by the client
u32 blocks_loaded = 0;
// Number of blocks with mesh in rendering range
@@ -230,6 +220,8 @@ void ClientMap::updateDrawList()
v3s16 camera_block = getContainerPos(cam_pos_nodes, MAP_BLOCKSIZE);
m_drawlist = std::map<v3s16, MapBlock*, MapBlockComparer>(MapBlockComparer(camera_block));
+ auto is_frustum_culled = m_client->getCamera()->getFrustumCuller();
+
// Uncomment to debug occluded blocks in the wireframe mode
// TODO: Include this as a flag for an extended debugging setting
//if (occlusion_culling_enabled && m_control.show_wireframe)
@@ -271,7 +263,7 @@ void ClientMap::updateDrawList()
// First, perform a simple distance check, with a padding of one extra block.
if (!m_control.range_all &&
- block_position.getDistanceFrom(cam_pos_nodes) > range + MAP_BLOCKSIZE)
+ block_position.getDistanceFrom(cam_pos_nodes) > m_control.wanted_range)
continue; // Out of range, skip.
// Keep the block alive as long as it is in range.
@@ -279,14 +271,18 @@ void ClientMap::updateDrawList()
blocks_in_range_with_mesh++;
// Frustum culling
- float d = 0.0;
- if (!isBlockInSight(block_coord, camera_position,
- camera_direction, camera_fov, range * BS, &d))
+ // Only do coarse culling here, to account for fast camera movement.
+ // This is needed because this function is not called every frame.
+ constexpr float frustum_cull_extra_radius = 300.0f;
+ v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
+ + block->mesh->getBoundingSphereCenter();
+ f32 mesh_sphere_radius = block->mesh->getBoundingRadius();
+ if (is_frustum_culled(mesh_sphere_center,
+ mesh_sphere_radius + frustum_cull_extra_radius))
continue;
// Occlusion culling
- if ((!m_control.range_all && d > m_control.wanted_range * BS) ||
- (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes))) {
+ if (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes)) {
blocks_occlusion_culled++;
continue;
}
@@ -358,33 +354,43 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
std::vector<DrawDescriptor> draw_order;
video::SMaterial previous_material;
+ auto is_frustum_culled = m_client->getCamera()->getFrustumCuller();
+
for (auto &i : m_drawlist) {
v3s16 block_pos = i.first;
MapBlock *block = i.second;
+ MapBlockMesh *block_mesh = block->mesh;
// If the mesh of the block happened to get deleted, ignore it
- if (!block->mesh)
+ if (!block_mesh)
+ continue;
+
+ // Do exact frustum culling
+ // (The one in updateDrawList is only coarse.)
+ v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
+ + block_mesh->getBoundingSphereCenter();
+ f32 mesh_sphere_radius = block_mesh->getBoundingRadius();
+ if (is_frustum_culled(mesh_sphere_center, mesh_sphere_radius))
continue;
v3f block_pos_r = intToFloat(block->getPosRelative() + MAP_BLOCKSIZE / 2, BS);
+
float d = camera_position.getDistanceFrom(block_pos_r);
d = MYMAX(0,d - BLOCK_MAX_RADIUS);
// Mesh animation
if (pass == scene::ESNRP_SOLID) {
- MapBlockMesh *mapBlockMesh = block->mesh;
- assert(mapBlockMesh);
// Pretty random but this should work somewhat nicely
bool faraway = d >= BS * 50;
- if (mapBlockMesh->isAnimationForced() || !faraway ||
+ if (block_mesh->isAnimationForced() || !faraway ||
mesh_animate_count < (m_control.range_all ? 200 : 50)) {
- bool animated = mapBlockMesh->animate(faraway, animation_time,
+ bool animated = block_mesh->animate(faraway, animation_time,
crack, daynight_ratio);
if (animated)
mesh_animate_count++;
} else {
- mapBlockMesh->decreaseAnimationForceTimer();
+ block_mesh->decreaseAnimationForceTimer();
}
}
@@ -394,17 +400,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
if (is_transparent_pass) {
// In transparent pass, the mesh will give us
// the partial buffers in the correct order
- for (auto &buffer : block->mesh->getTransparentBuffers())
+ for (auto &buffer : block_mesh->getTransparentBuffers())
draw_order.emplace_back(block_pos, &buffer);
}
else {
// otherwise, group buffers across meshes
// using MeshBufListList
- MapBlockMesh *mapBlockMesh = block->mesh;
- assert(mapBlockMesh);
-
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
- scene::IMesh *mesh = mapBlockMesh->getMesh(layer);
+ scene::IMesh *mesh = block_mesh->getMesh(layer);
assert(mesh);
u32 c = mesh->getMeshBufferCount();
@@ -772,9 +775,9 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
for (auto &lists : grouped_buffers.lists)
for (MeshBufList &list : lists)
buffer_count += list.bufs.size();
-
+
draw_order.reserve(draw_order.size() + buffer_count);
-
+
// Capture draw order for all solid meshes
for (auto &lists : grouped_buffers.lists) {
for (MeshBufList &list : lists) {
@@ -908,8 +911,8 @@ void ClientMap::updateTransparentMeshBuffers()
MapBlock* block = it->second;
if (!block->mesh)
continue;
-
- if (m_needs_update_transparent_meshes ||
+
+ if (m_needs_update_transparent_meshes ||
block->mesh->getTransparentBuffers().size() == 0) {
v3s16 block_pos = block->getPos();