From 225e69063fa0c3dc96f960aa79dfc568fe3d89a8 Mon Sep 17 00:00:00 2001 From: hecks <42101236+hecktest@users.noreply.github.com> Date: Fri, 26 Feb 2021 21:23:46 +0100 Subject: Keep mapblocks in memory if they're in range (#10714) Some other minor parts of clientmap.cpp have been cleaned up along the way --- src/client/clientmap.cpp | 45 ++++++++++++++++++++++++--------------------- src/util/numeric.cpp | 8 ++------ src/util/numeric.h | 4 ++++ 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index b9e0cc2ce..be8343009 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -165,6 +165,9 @@ void ClientMap::updateDrawList() 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 @@ -182,6 +185,7 @@ void ClientMap::updateDrawList() occlusion_culling_enabled = false; } + // 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) @@ -218,32 +222,34 @@ void ClientMap::updateDrawList() continue; } - float range = 100000 * BS; - if (!m_control.range_all) - range = m_control.wanted_range * BS; + v3s16 block_coord = block->getPos(); + v3s16 block_position = block->getPosRelative() + MAP_BLOCKSIZE / 2; - float d = 0.0; - if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, camera_fov, range, &d)) - continue; + // 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) + continue; // Out of range, skip. + // Keep the block alive as long as it is in range. + block->resetUsageTimer(); blocks_in_range_with_mesh++; - /* - Occlusion culling - */ + // Frustum culling + float d = 0.0; + if (!isBlockInSight(block_coord, camera_position, + camera_direction, camera_fov, range * BS, &d)) + continue; + + // Occlusion culling if ((!m_control.range_all && d > m_control.wanted_range * BS) || (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes))) { blocks_occlusion_culled++; continue; } - // This block is in range. Reset usage timer. - block->resetUsageTimer(); - // Add to set block->refGrab(); - m_drawlist[block->getPos()] = block; + m_drawlist[block_coord] = block; sector_blocks_drawn++; } // foreach sectorblocks @@ -282,8 +288,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) const u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); const v3f camera_position = m_camera_position; - const v3f camera_direction = m_camera_direction; - const f32 camera_fov = m_camera_fov; /* Get all blocks and draw all visible ones @@ -310,11 +314,10 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) if (!block->mesh) continue; - float d = 0.0; - if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, camera_fov, 100000 * BS, &d)) - 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) { //MutexAutoLock lock(block->mesh_mutex); diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 1af3f66be..99e4cfb5c 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -106,10 +106,6 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed) bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr) { - // Maximum radius of a block. The magic number is - // sqrt(3.0) / 2.0 in literal form. - static constexpr const f32 block_max_radius = 0.866025403784f * MAP_BLOCKSIZE * BS; - v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE; // Block center position @@ -123,7 +119,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, v3f blockpos_relative = blockpos - camera_pos; // Total distance - f32 d = MYMAX(0, blockpos_relative.getLength() - block_max_radius); + f32 d = MYMAX(0, blockpos_relative.getLength() - BLOCK_MAX_RADIUS); if (distance_ptr) *distance_ptr = d; @@ -141,7 +137,7 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, // such that a block that has any portion visible with the // current camera position will have the center visible at the // adjusted postion - f32 adjdist = block_max_radius / cos((M_PI - camera_fov) / 2); + f32 adjdist = BLOCK_MAX_RADIUS / cos((M_PI - camera_fov) / 2); // Block position relative to adjusted camera v3f blockpos_adj = blockpos - (camera_pos - camera_dir * adjdist); diff --git a/src/util/numeric.h b/src/util/numeric.h index 864ab7543..32a6f4312 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once #include "basic_macros.h" +#include "constants.h" #include "irrlichttypes.h" #include "irr_v2d.h" #include "irr_v3d.h" @@ -36,6 +37,9 @@ with this program; if not, write to the Free Software Foundation, Inc., y = temp; \ } while (0) +// Maximum radius of a block. The magic number is +// sqrt(3.0) / 2.0 in literal form. +static constexpr const f32 BLOCK_MAX_RADIUS = 0.866025403784f * MAP_BLOCKSIZE * BS; inline s16 getContainerPos(s16 p, s16 d) { -- cgit v1.2.3