diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index e876c9efc..129689e9e 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -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 §or_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 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 §or_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; + + 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. 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.