Corrections to loops and BFS cullers (#13375)

* Reset usage timers in loops culler
* Correctly touch map blocks when using bfs culler
* Align use of variables
* Report statistics when using loop culler
This commit is contained in:
x2048 2023-04-01 22:41:00 +02:00 committed by GitHub
parent 819e9fc615
commit 6c0a6925fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 48 additions and 22 deletions

View File

@ -269,6 +269,10 @@ void ClientMap::updateDrawList()
const v3s16 cam_pos_nodes = floatToInt(m_camera_position, BS); const 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);
// Number of blocks occlusion culled // Number of blocks occlusion culled
u32 blocks_occlusion_culled = 0; u32 blocks_occlusion_culled = 0;
// Number of blocks frustum culled // Number of blocks frustum culled
@ -304,12 +308,23 @@ void ClientMap::updateDrawList()
frustum and display them. frustum and display them.
*/ */
if (m_control.range_all || m_loops_occlusion_culler) { if (m_control.range_all || m_loops_occlusion_culler) {
// Number of blocks currently loaded by the client
u32 blocks_loaded = 0;
// Number of blocks with mesh in rendering range
u32 blocks_in_range_with_mesh = 0;
MapBlockVect sectorblocks; MapBlockVect sectorblocks;
for (auto &sector_it : m_sectors) { for (auto &sector_it : m_sectors) {
MapSector *sector = sector_it.second; MapSector *sector = sector_it.second;
if (!sector) v2s16 sp = sector->getPos();
continue;
blocks_loaded += sector->size();
if (!m_control.range_all) {
if (sp.X < p_blocks_min.X || sp.X > p_blocks_max.X ||
sp.Y < p_blocks_min.Z || sp.Y > p_blocks_max.Z)
continue;
}
sectorblocks.clear(); sectorblocks.clear();
sector->getBlocks(sectorblocks); sector->getBlocks(sectorblocks);
@ -334,6 +349,16 @@ void ClientMap::updateDrawList()
mesh_sphere_radius = 0.0f; mesh_sphere_radius = 0.0f;
} }
// First, perform a simple distance check.
if (!m_control.range_all &&
mesh_sphere_center.getDistanceFrom(m_camera_position) >
m_control.wanted_range * BS + mesh_sphere_radius)
continue; // Out of range, skip.
// Keep the block alive as long as it is in range.
block->resetUsageTimer();
blocks_in_range_with_mesh++;
// Frustum culling // Frustum culling
// Only do coarse culling here, to account for fast camera movement. // Only do coarse culling here, to account for fast camera movement.
// This is needed because this function is not called every frame. // This is needed because this function is not called every frame.
@ -345,7 +370,7 @@ void ClientMap::updateDrawList()
} }
// Raytraced occlusion culling - send rays from the camera to the block's corners // Raytraced occlusion culling - send rays from the camera to the block's corners
if (occlusion_culling_enabled && m_enable_raytraced_culling && if (!m_control.range_all && occlusion_culling_enabled && m_enable_raytraced_culling &&
mesh && mesh &&
isMeshOccluded(block, mesh_grid.cell_size, cam_pos_nodes)) { isMeshOccluded(block, mesh_grid.cell_size, cam_pos_nodes)) {
blocks_occlusion_culled++; blocks_occlusion_culled++;
@ -367,16 +392,15 @@ void ClientMap::updateDrawList()
} }
} }
} }
g_profiler->avg("MapBlock meshes in range [#]", blocks_in_range_with_mesh);
g_profiler->avg("MapBlocks loaded [#]", blocks_loaded);
} else { } else {
// Blocks visited by the algorithm // Blocks visited by the algorithm
u32 blocks_visited = 0; u32 blocks_visited = 0;
// Block sides that were not traversed // Block sides that were not traversed
u32 sides_skipped = 0; u32 sides_skipped = 0;
v3s16 p_blocks_min;
v3s16 p_blocks_max;
getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max);
std::queue<v3s16> blocks_to_consider; std::queue<v3s16> blocks_to_consider;
v3s16 camera_mesh = mesh_grid.getMeshPos(camera_block); v3s16 camera_mesh = mesh_grid.getMeshPos(camera_block);
@ -595,7 +619,7 @@ void ClientMap::updateDrawList()
void ClientMap::touchMapBlocks() void ClientMap::touchMapBlocks()
{ {
if (!m_loops_occlusion_culler) if (m_control.range_all || m_loops_occlusion_culler)
return; return;
v3s16 cam_pos_nodes = floatToInt(m_camera_position, BS); v3s16 cam_pos_nodes = floatToInt(m_camera_position, BS);
@ -609,8 +633,6 @@ void ClientMap::touchMapBlocks()
// Number of blocks with mesh in rendering range // Number of blocks with mesh in rendering range
u32 blocks_in_range_with_mesh = 0; u32 blocks_in_range_with_mesh = 0;
v3f cam_pos_f = intToFloat(cam_pos_nodes, BS);
for (const auto &sector_it : m_sectors) { for (const auto &sector_it : m_sectors) {
MapSector *sector = sector_it.second; MapSector *sector = sector_it.second;
v2s16 sp = sector->getPos(); v2s16 sp = sector->getPos();
@ -630,23 +652,27 @@ void ClientMap::touchMapBlocks()
*/ */
for (MapBlock *block : sectorblocks) { for (MapBlock *block : sectorblocks) {
/* MapBlockMesh *mesh = block->mesh;
Compare block position to camera position, skip
if not seen on display
*/
if (!block->mesh) { // Calculate the coordinates for range and frustum culling
// Ignore if mesh doesn't exist v3f mesh_sphere_center;
continue; f32 mesh_sphere_radius;
v3s16 block_pos_nodes = block->getPos() * MAP_BLOCKSIZE;
if (mesh) {
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
+ mesh->getBoundingSphereCenter();
mesh_sphere_radius = mesh->getBoundingRadius();
} else {
mesh_sphere_center = intToFloat(block_pos_nodes, BS)
+ v3f((MAP_BLOCKSIZE * 0.5f - 0.5f) * BS);
mesh_sphere_radius = 0.0f;
} }
v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
+ block->mesh->getBoundingSphereCenter();
f32 mesh_sphere_radius = block->mesh->getBoundingRadius();
// First, perform a simple distance check. // First, perform a simple distance check.
if (!m_control.range_all && if (!m_control.range_all &&
mesh_sphere_center.getDistanceFrom(cam_pos_f) > mesh_sphere_center.getDistanceFrom(m_camera_position) >
m_control.wanted_range * BS + mesh_sphere_radius) m_control.wanted_range * BS + mesh_sphere_radius)
continue; // Out of range, skip. continue; // Out of range, skip.