Allow zoom to actually show more data.
authorLars Hofhansl <larsh@apache.org>
Thu, 16 Nov 2017 05:58:23 +0000 (21:58 -0800)
committerLars Hofhansl <larsh@apache.org>
Thu, 16 Nov 2017 06:03:58 +0000 (22:03 -0800)
This allows the client to retrieve blocks at a greater distance
from the server, thus allowing for a real zoom.

src/camera.cpp
src/clientiface.cpp
src/util/numeric.cpp
src/util/numeric.h

index e0028f480f635a06e6f3f547a86beb7facbdbece..62acbe26dd7ca6dc0602e81d64986083c2804ea6 100644 (file)
@@ -458,7 +458,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r
        } else {
                fov_degrees = m_cache_fov;
        }
-       fov_degrees = rangelim(fov_degrees, 7.0, 160.0);
+       fov_degrees = rangelim(fov_degrees, 1.0, 160.0);
 
        // FOV and aspect ratio
        const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
@@ -550,7 +550,8 @@ void Camera::updateViewingRange()
 {
        f32 viewing_range = g_settings->getFloat("viewing_range");
        f32 near_plane = g_settings->getFloat("near_plane");
-       m_draw_control.wanted_range = viewing_range;
+
+       m_draw_control.wanted_range = std::fmin(adjustDist(viewing_range, getFovMax()), 4000);
        m_cameranode->setNearValue(rangelim(near_plane, 0.0f, 0.5f) * BS);
        if (m_draw_control.range_all) {
                m_cameranode->setFarValue(100000.0);
index bf0bdade081fbd9fdd0bada25163885c4feba03a..8e469cafbb7aad97e0eedc080f357a8e0f17ea99 100644 (file)
@@ -196,6 +196,20 @@ void RemoteClient::GetNextBlocks (
        s16 wanted_range = sao->getWantedRange() + 1;
        float camera_fov = sao->getFov();
 
+       const s16 full_d_max = std::min(adjustDist(m_max_send_distance, camera_fov), wanted_range);
+       const s16 d_opt = std::min(adjustDist(m_block_optimize_distance, camera_fov), wanted_range);
+       const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
+       infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
+
+       s16 d_max = full_d_max;
+       s16 d_max_gen = std::min(adjustDist(m_max_gen_distance, camera_fov), wanted_range);
+
+       // Don't loop very much at a time, adjust with distance,
+       // do more work per RTT with greater distances.
+       s16 max_d_increment_at_time = full_d_max / 9 + 1;
+       if (d_max > d_start + max_d_increment_at_time)
+               d_max = d_start + max_d_increment_at_time;
+
        // cos(angle between velocity and camera) * |velocity|
        // Limit to 0.0f in case player moves backwards.
        f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
@@ -204,19 +218,6 @@ void RemoteClient::GetNextBlocks (
        // limit max fov effect to 50%, 60% at 20n/s fly speed
        camera_fov = camera_fov / (1 + dot / 300.0f);
 
-       const s16 full_d_max = std::min(m_max_send_distance, wanted_range);
-       const s16 d_opt = std::min(m_block_optimize_distance, wanted_range);
-       const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
-       //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
-
-       s16 d_max = full_d_max;
-       s16 d_max_gen = std::min(m_max_gen_distance, wanted_range);
-
-       // Don't loop very much at a time
-       s16 max_d_increment_at_time = 2;
-       if (d_max > d_start + max_d_increment_at_time)
-               d_max = d_start + max_d_increment_at_time;
-
        s32 nearest_emerged_d = -1;
        s32 nearest_emergefull_d = -1;
        s32 nearest_sent_d = -1;
index ebc81185f3918b187a84fe461af24fe84cd83f43..12c91be913ff05ce3a2529781703998d0e40cf30 100644 (file)
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "noise.h" // PseudoRandom, PcgRandom
 #include "threading/mutex_auto_lock.h"
 #include <cstring>
+#include <cmath>
 
 
 // myrand
@@ -161,3 +162,16 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
 
        return true;
 }
+
+s16 adjustDist(s16 dist, float zoom_fov)
+{
+       // 1.775 ~= 72 * PI / 180 * 1.4, the default on the client
+       const float default_fov = 1.775f;
+       // heuristic cut-off for zooming
+       if (zoom_fov > default_fov / 2.0f)
+               return dist;
+
+       // new_dist = dist * ((1 - cos(FOV / 2)) / (1-cos(zoomFOV /2))) ^ (1/3)
+       return round(dist * cbrt((1.0f - cos(default_fov / 2.0f)) /
+               (1.0f - cos(zoom_fov / 2.0f))));
+}
index 347e7a49ea9939fb93b5d2cf723fb93ce4edb780..8ee2d585c1370e4780822e73e8824a29d9061e88 100644 (file)
@@ -232,6 +232,8 @@ 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=NULL);
 
+s16 adjustDist(s16 dist, float zoom_fov);
+
 /*
        Returns nearest 32-bit integer for given floating point number.
        <cmath> and <math.h> in VC++ don't provide round().