new viewing range updater algorithm
authorPerttu Ahola <celeron55@gmail.com>
Sun, 26 Dec 2010 01:58:19 +0000 (03:58 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 26 Dec 2010 01:58:19 +0000 (03:58 +0200)
src/client.cpp
src/client.h
src/main.cpp
src/map.cpp
src/map.h

index b0750cae6ede2d24067e80f5eadefa27375d2790..d43b97a3ceb1952188de3738b05cdd316ba7f4c3 100644 (file)
@@ -67,7 +67,7 @@ Client::Client(
                IrrlichtDevice *device,
                const char *playername,
                JMutex &range_mutex,
-               s16 &viewing_range_nodes,
+               float &viewing_range_nodes,
                bool &viewing_range_all):
        m_thread(this),
        m_env(new ClientMap(this,
index b29358d93c29fc863a886b7d133447e8446e47e2..e48c8ec69e2aa6deae433e0a8631adfad14d9eb8 100644 (file)
@@ -111,7 +111,7 @@ public:
                        IrrlichtDevice *device,
                        const char *playername,
                        JMutex &range_mutex,
-                       s16 &viewing_range_nodes,
+                       float &viewing_range_nodes,
                        bool &viewing_range_all
                        );
        
index d22da3ff786af4a142b42419156fcc2d4ac3a109..b7a1b6b328c5f3fa625c30f3bb86ec22e599d278 100644 (file)
@@ -257,7 +257,7 @@ IrrlichtWrapper *g_irrlicht;
 JMutex g_range_mutex;\r
 \r
 // Blocks are viewed in this range from the player\r
-s16 g_viewing_range_nodes = 60;\r
+float g_viewing_range_nodes = 60;\r
 //s16 g_viewing_range_nodes = 0;\r
 \r
 // This is updated by the client's fetchBlocks routine\r
@@ -849,6 +849,7 @@ private:
        bool rightclicked;\r
 };\r
 \r
+#if 0\r
 void updateViewingRange(f32 frametime, Client *client)\r
 {\r
        // Range_all messes up frametime_avg\r
@@ -860,6 +861,9 @@ void updateViewingRange(f32 frametime, Client *client)
        // Initialize to the target value\r
        static float frametime_avg = 1.0/wanted_fps;\r
        //frametime_avg = frametime_avg * 0.9 + frametime * 0.1;\r
+       //frametime_avg = frametime_avg * 0.7 + frametime * 0.3;\r
+       //frametime_avg = frametime_avg * 0.5 + frametime * 0.5;\r
+       //frametime_avg = frametime_avg * 0.0 + frametime * 1.0;\r
        frametime_avg = frametime_avg * 0.7 + frametime * 0.3;\r
 \r
        static f32 counter = 0;\r
@@ -869,6 +873,8 @@ void updateViewingRange(f32 frametime, Client *client)
        }\r
        //counter = 1.0; //seconds\r
        counter = 0.5; //seconds\r
+       //counter += 0.1; //seconds\r
+       //counter = 0.3; //seconds\r
 \r
        //float freetime_ratio = 0.2;\r
        //float freetime_ratio = 0.4;\r
@@ -876,7 +882,20 @@ void updateViewingRange(f32 frametime, Client *client)
 \r
        float frametime_wanted = (1.0/(wanted_fps/(1.0-freetime_ratio)));\r
 \r
-       float fraction = sqrt(frametime_avg / frametime_wanted);\r
+       //float fraction = sqrt(frametime_avg / frametime_wanted);\r
+       //float fraction = pow(frametime_avg / frametime_wanted, 1./3);\r
+\r
+       float fraction_unbiased = frametime_avg / frametime_wanted;\r
+\r
+       float fraction = pow(fraction_unbiased, 20./(float)g_viewing_range_nodes);\r
+       \r
+       /*float fraction = 1.0;\r
+       // If frametime is too high\r
+       if(fraction_unbiased > 1.0)\r
+               fraction = pow(fraction_unbiased, 1./2);\r
+       // If frametime is too low\r
+       else\r
+               fraction = pow(fraction_unbiased, 1./5);*/\r
 \r
        /*float fraction = sqrt(frametime_avg / frametime_wanted) / 2.0\r
                        + frametime_avg / frametime_wanted / 2.0;*/\r
@@ -887,8 +906,19 @@ void updateViewingRange(f32 frametime, Client *client)
        \r
        //float fraction_good_threshold = 0.1;\r
        //float fraction_bad_threshold = 0.25;\r
-       float fraction_good_threshold = 0.075;\r
-       float fraction_bad_threshold = 0.125;\r
+\r
+       /*float fraction_good_threshold = 0.075;\r
+       float fraction_bad_threshold = 0.125;*/\r
+       // If frametime is too low\r
+       /*if(fraction < 1.0)\r
+       {\r
+               fraction_good_threshold = pow(fraction_good_threshold, 4);\r
+               fraction_bad_threshold = pow(fraction_bad_threshold, 4);\r
+       }*/\r
+\r
+       float fraction_good_threshold = 0.23;\r
+       float fraction_bad_threshold = 0.33;\r
+       \r
        float fraction_limit;\r
        // Use high limit if fraction is good AND the fraction would\r
        // lower the range. We want to keep the range fairly high.\r
@@ -897,7 +927,8 @@ void updateViewingRange(f32 frametime, Client *client)
        else\r
                fraction_limit = fraction_good_threshold;\r
 \r
-       if(fabs(fraction - 1.0) < fraction_limit)\r
+       //if(fabs(fraction - 1.0) < fraction_limit)\r
+       if(fabs(fraction_unbiased - 1.0) < fraction_limit)\r
        {\r
                fraction_is_good = true;\r
                return;\r
@@ -934,6 +965,113 @@ void updateViewingRange(f32 frametime, Client *client)
        /*dstream<<"g_viewing_range_nodes = "\r
                        <<g_viewing_range_nodes<<std::endl;*/\r
 }\r
+#endif\r
+\r
+void updateViewingRange(f32 frametime_in, Client *client)\r
+{\r
+       if(g_viewing_range_all == true)\r
+               return;\r
+       \r
+       static f32 added_frametime = 0;\r
+       static s16 added_frames = 0;\r
+\r
+       added_frametime += frametime_in;\r
+       added_frames += 1;\r
+\r
+       // Actually this counter kind of sucks because frametime is busytime\r
+       static f32 counter = 0;\r
+       counter -= frametime_in;\r
+       if(counter > 0)\r
+               return;\r
+       //counter = 0.1;\r
+       counter = 0.2;\r
+\r
+       dstream<<__FUNCTION_NAME\r
+                       <<": Collected "<<added_frames<<" frames, total of "\r
+                       <<added_frametime<<"s."<<std::endl;\r
+       \r
+       f32 frametime = added_frametime / added_frames;\r
+       added_frametime = 0.0;\r
+       added_frames = 0;\r
+       \r
+       float wanted_fps = g_settings.getFloat("wanted_fps");\r
+       float wanted_frametime = 1.0 / wanted_fps;\r
+       \r
+       f32 wanted_frametime_change = wanted_frametime - frametime;\r
+       dstream<<"wanted_frametime_change="<<wanted_frametime_change<<std::endl;\r
+       \r
+       // If needed frametime change is very small, just return\r
+       if(fabs(wanted_frametime_change) < wanted_frametime*0.2)\r
+       {\r
+               dstream<<"ignoring small wanted_frametime_change"<<std::endl;\r
+               return;\r
+       }\r
+\r
+       float range = g_viewing_range_nodes;\r
+       float new_range = range;\r
+\r
+       static s16 range_old = 0;\r
+       static f32 frametime_old = 0;\r
+       \r
+       float d_range = range - range_old;\r
+       f32 d_frametime = frametime - frametime_old;\r
+       // A sane default of 30ms per 50 nodes of range\r
+       static f32 time_per_range = 30. / 50;\r
+       if(d_range != 0)\r
+       {\r
+               time_per_range = d_frametime / d_range;\r
+       }\r
+       \r
+       // The minimum allowed calculated frametime-range derivative:\r
+       // Practically this sets the maximum speed of changing the range.\r
+       // The lower this value, the higher the maximum changing speed.\r
+       // A low value here results in wobbly range (0.001)\r
+       // A high value here results in slow changing range (0.0025)\r
+       // SUGG: This could be dynamically adjusted so that when\r
+       //       the camera is turning, this is lower\r
+       float min_time_per_range = 0.001;\r
+       if(time_per_range < min_time_per_range)\r
+               time_per_range = min_time_per_range;\r
+       \r
+       dstream<<"time_per_range="<<time_per_range<<std::endl;\r
+\r
+       f32 wanted_range_change = wanted_frametime_change / time_per_range;\r
+       // Dampen the change a bit to kill oscillations\r
+       //wanted_range_change *= 0.9;\r
+       wanted_range_change *= 0.75;\r
+       dstream<<"wanted_range_change="<<wanted_range_change<<std::endl;\r
+\r
+       // If needed range change is very small, just return\r
+       if(fabs(wanted_range_change) < 0.001)\r
+       {\r
+               dstream<<"ignoring small wanted_range_change"<<std::endl;\r
+               return;\r
+       }\r
+\r
+       new_range += wanted_range_change;\r
+       dstream<<"new_range="<<new_range/*<<std::endl*/;\r
+       \r
+       float range_min = g_settings.getS16("viewing_range_nodes_min");\r
+       float range_max = g_settings.getS16("viewing_range_nodes_max");\r
+       \r
+       float new_range_unclamped = new_range;\r
+       if(new_range < range_min)\r
+               new_range = range_min;\r
+       if(new_range > range_max)\r
+               new_range = range_max;\r
+       \r
+       if(new_range != new_range_unclamped)\r
+               dstream<<", clamped to "<<new_range<<std::endl;\r
+       else\r
+               dstream<<std::endl;\r
+\r
+       JMutexAutoLock lock(g_range_mutex);\r
+\r
+       g_viewing_range_nodes = new_range;\r
+\r
+       range_old = new_range;\r
+       frametime_old = frametime;\r
+}\r
 \r
 class GUIQuickInventory : public IEventReceiver\r
 {\r
@@ -2326,13 +2464,15 @@ int main(int argc, char *argv[])
                        swprintf(temptext, 150,\r
                                        L"(% .1f, % .1f, % .1f)"\r
                                        L" (% .3f < btime_jitter < % .3f"\r
-                                       L", dtime_jitter = % .1f %%)",\r
+                                       L", dtime_jitter = % .1f %%"\r
+                                       L", v_range = %.1f)",\r
                                        player_position.X/BS,\r
                                        player_position.Y/BS,\r
                                        player_position.Z/BS,\r
                                        busytime_jitter1_min_sample,\r
                                        busytime_jitter1_max_sample,\r
-                                       dtime_jitter1_max_fraction * 100.0\r
+                                       dtime_jitter1_max_fraction * 100.0,\r
+                                       g_viewing_range_nodes\r
                                        );\r
 \r
                        guitext2->setText(temptext);\r
index 59053f70c7e346950117596acff20cbb7d1584cb..d5a61d408f0c49d4101d4b774ecb96168b5bc4ee 100644 (file)
@@ -2890,7 +2890,7 @@ void ServerMap::PrintInfo(std::ostream &out)
 ClientMap::ClientMap(
                Client *client,
                JMutex &range_mutex,
-               s16 &viewing_range_nodes,
+               float &viewing_range_nodes,
                bool &viewing_range_all,
                scene::ISceneNode* parent,
                scene::ISceneManager* mgr,
@@ -3013,7 +3013,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                all changed nodes in viewing range at the next step.
        */
 
-       s16 viewing_range_nodes;
+       float viewing_range_nodes;
        bool viewing_range_all;
        {
                JMutexAutoLock lock(m_range_mutex);
index 3c3fe9dafab9f2648fbee5c0642301bd05337666..8952bc1108faae56aab8a99afe9feace4da14b53 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -551,7 +551,7 @@ public:
        ClientMap(
                        Client *client,
                        JMutex &range_mutex,
-                       s16 &viewing_range_nodes,
+                       float &viewing_range_nodes,
                        bool &viewing_range_all,
                        scene::ISceneNode* parent,
                        scene::ISceneManager* mgr,
@@ -620,7 +620,7 @@ private:
        JMutex mesh_mutex;
 
        JMutex &m_range_mutex;
-       s16 &m_viewing_range_nodes;
+       float &m_viewing_range_nodes;
        bool &m_viewing_range_all;
 };