]> git.lizzy.rs Git - minetest.git/commitdiff
Corrections to loops and BFS cullers (#13375)
authorx2048 <codeforsmile@gmail.com>
Sat, 1 Apr 2023 20:41:00 +0000 (22:41 +0200)
committerGitHub <noreply@github.com>
Sat, 1 Apr 2023 20:41:00 +0000 (22:41 +0200)
* Reset usage timers in loops culler
* Correctly touch map blocks when using bfs culler
* Align use of variables
* Report statistics when using loop culler

src/client/clientmap.cpp

index e876c9efc2e3143c4fd1dfd6c7c0b328e84f912e..129689e9e5638d9e7815f83b71a77c6a01c609fe 100644 (file)
@@ -269,6 +269,10 @@ void ClientMap::updateDrawList()
 
        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
        u32 blocks_occlusion_culled = 0;
        // Number of blocks frustum culled
@@ -304,12 +308,23 @@ void ClientMap::updateDrawList()
         frustum and display them.
         */
        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;
 
                for (auto &sector_it : m_sectors) {
                        MapSector *sector = sector_it.second;
-                       if (!sector)
-                               continue;
+                       v2s16 sp = sector->getPos();
+
+                       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();
                        sector->getBlocks(sectorblocks);
@@ -334,6 +349,16 @@ void ClientMap::updateDrawList()
                                        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
                                // Only do coarse culling here, to account for fast camera movement.
                                // 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
-                               if (occlusion_culling_enabled && m_enable_raytraced_culling &&
+                               if (!m_control.range_all && occlusion_culling_enabled && m_enable_raytraced_culling &&
                                                mesh &&
                                                isMeshOccluded(block, mesh_grid.cell_size, cam_pos_nodes)) {
                                        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 {
                // Blocks visited by the algorithm
                u32 blocks_visited = 0;
                // Block sides that were not traversed
                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;
 
                v3s16 camera_mesh = mesh_grid.getMeshPos(camera_block);
@@ -595,7 +619,7 @@ void ClientMap::updateDrawList()
 
 void ClientMap::touchMapBlocks()
 {
-       if (!m_loops_occlusion_culler)
+       if (m_control.range_all || m_loops_occlusion_culler)
                return;
 
        v3s16 cam_pos_nodes = floatToInt(m_camera_position, BS);
@@ -609,8 +633,6 @@ void ClientMap::touchMapBlocks()
        // Number of blocks with mesh in rendering range
        u32 blocks_in_range_with_mesh = 0;
 
-       v3f cam_pos_f = intToFloat(cam_pos_nodes, BS);
-
        for (const auto &sector_it : m_sectors) {
                MapSector *sector = sector_it.second;
                v2s16 sp = sector->getPos();
@@ -630,23 +652,27 @@ void ClientMap::touchMapBlocks()
                */
 
                for (MapBlock *block : sectorblocks) {
-                       /*
-                               Compare block position to camera position, skip
-                               if not seen on display
-                       */
+                       MapBlockMesh *mesh = block->mesh;
 
-                       if (!block->mesh) {
-                               // Ignore if mesh doesn't exist
-                               continue;
-                       }
+                       // Calculate the coordinates for range and frustum culling
+                       v3f mesh_sphere_center;
+                       f32 mesh_sphere_radius;
+
+                       v3s16 block_pos_nodes = block->getPos() * MAP_BLOCKSIZE;
 
-                       v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
-                                       + block->mesh->getBoundingSphereCenter();
-                       f32 mesh_sphere_radius = block->mesh->getBoundingRadius();
+                       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;
+                       }
 
                        // First, perform a simple distance check.
                        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)
                                continue; // Out of range, skip.