drawing range updater update and myrand() (but not usage of it)
authorPerttu Ahola <celeron55@gmail.com>
Sun, 26 Dec 2010 11:33:20 +0000 (13:33 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 26 Dec 2010 11:33:20 +0000 (13:33 +0200)
src/client.cpp
src/client.h
src/main.cpp
src/map.cpp
src/map.h
src/servermain.cpp
src/utility.cpp
src/utility.h

index d43b97a3ceb1952188de3738b05cdd316ba7f4c3..af2b375f48dbf52d5f81f72ce38e07c5c9d358bb 100644 (file)
@@ -66,14 +66,9 @@ void * ClientUpdateThread::Thread()
 Client::Client(
                IrrlichtDevice *device,
                const char *playername,
-               JMutex &range_mutex,
-               float &viewing_range_nodes,
-               bool &viewing_range_all):
+               MapDrawControl &control):
        m_thread(this),
-       m_env(new ClientMap(this,
-                       range_mutex,
-                       viewing_range_nodes,
-                       viewing_range_all,
+       m_env(new ClientMap(this, control,
                        device->getSceneManager()->getRootSceneNode(),
                        device->getSceneManager(), 666),
                        dout_client),
index e48c8ec69e2aa6deae433e0a8631adfad14d9eb8..c56b615cb6d86edb08dcd3684ce1a2a2ee20ae3a 100644 (file)
@@ -110,9 +110,7 @@ public:
        Client(
                        IrrlichtDevice *device,
                        const char *playername,
-                       JMutex &range_mutex,
-                       float &viewing_range_nodes,
-                       bool &viewing_range_all
+                       MapDrawControl &control
                        );
        
        ~Client();
index b7a1b6b328c5f3fa625c30f3bb86ec22e599d278..2f22caeb011b499cc5fe076eba5d6048cd426154 100644 (file)
@@ -253,25 +253,7 @@ TODO: Fix viewing range updater's oscillation when there is large non-
 \r
 IrrlichtWrapper *g_irrlicht;\r
 \r
-// All range-related stuff below is locked behind this\r
-JMutex g_range_mutex;\r
-\r
-// Blocks are viewed in this range from the player\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
-//s16 g_actual_viewing_range_nodes = VIEWING_RANGE_NODES_DEFAULT;\r
-\r
-// If true, the preceding value has no meaning and all blocks\r
-// already existing in memory are drawn\r
-bool g_viewing_range_all = false;\r
-\r
-// This is the freetime ratio imposed by the dynamic viewing\r
-// range changing code.\r
-// It is controlled by the main loop to the smallest value that\r
-// inhibits glitches (dtime jitter) in the main loop.\r
-//float g_freetime_ratio = FREETIME_RATIO_MAX;\r
+MapDrawControl draw_control;\r
 \r
 /*\r
        Settings.\r
@@ -455,15 +437,14 @@ public:
                                // Viewing range selection\r
                                if(event.KeyInput.Key == irr::KEY_KEY_R)\r
                                {\r
-                                       JMutexAutoLock lock(g_range_mutex);\r
-                                       if(g_viewing_range_all)\r
+                                       if(draw_control.range_all)\r
                                        {\r
-                                               g_viewing_range_all = false;\r
+                                               draw_control.range_all = false;\r
                                                dstream<<DTIME<<"Disabled full viewing range"<<std::endl;\r
                                        }\r
                                        else\r
                                        {\r
-                                               g_viewing_range_all = true;\r
+                                               draw_control.range_all = true;\r
                                                dstream<<DTIME<<"Enabled full viewing range"<<std::endl;\r
                                        }\r
                                }\r
@@ -853,7 +834,7 @@ private:
 void updateViewingRange(f32 frametime, Client *client)\r
 {\r
        // Range_all messes up frametime_avg\r
-       if(g_viewing_range_all == true)\r
+       if(draw_control.range_all == true)\r
                return;\r
 \r
        float wanted_fps = g_settings.getFloat("wanted_fps");\r
@@ -887,7 +868,7 @@ void updateViewingRange(f32 frametime, Client *client)
 \r
        float fraction_unbiased = frametime_avg / frametime_wanted;\r
 \r
-       float fraction = pow(fraction_unbiased, 20./(float)g_viewing_range_nodes);\r
+       float fraction = pow(fraction_unbiased, 20./(float)draw_control.wanted_range);\r
        \r
        /*float fraction = 1.0;\r
        // If frametime is too high\r
@@ -948,7 +929,7 @@ void updateViewingRange(f32 frametime, Client *client)
        s16 viewing_range_nodes_min = g_settings.getS16("viewing_range_nodes_min");\r
        s16 viewing_range_nodes_max = g_settings.getS16("viewing_range_nodes_max");\r
 \r
-       s16 n = (float)g_viewing_range_nodes / fraction;\r
+       s16 n = (float)draw_control.wanted_range / fraction;\r
        if(n < viewing_range_nodes_min)\r
                n = viewing_range_nodes_min;\r
        if(n > viewing_range_nodes_max)\r
@@ -956,20 +937,20 @@ void updateViewingRange(f32 frametime, Client *client)
 \r
        bool can_change = true;\r
 \r
-       if(client->isFetchingBlocks() == true && n > g_viewing_range_nodes)\r
+       if(client->isFetchingBlocks() == true && n > draw_control.wanted_range)\r
                can_change = false;\r
        \r
        if(can_change)\r
-               g_viewing_range_nodes = n;\r
+               draw_control.wanted_range = n;\r
 \r
-       /*dstream<<"g_viewing_range_nodes = "\r
-                       <<g_viewing_range_nodes<<std::endl;*/\r
+       /*dstream<<"draw_control.wanted_range = "\r
+                       <<draw_control.wanted_range<<std::endl;*/\r
 }\r
 #endif\r
 \r
 void updateViewingRange(f32 frametime_in, Client *client)\r
 {\r
-       if(g_viewing_range_all == true)\r
+       if(draw_control.range_all == true)\r
                return;\r
        \r
        static f32 added_frametime = 0;\r
@@ -990,7 +971,29 @@ void updateViewingRange(f32 frametime_in, Client *client)
                        <<": Collected "<<added_frames<<" frames, total of "\r
                        <<added_frametime<<"s."<<std::endl;\r
        \r
-       f32 frametime = added_frametime / added_frames;\r
+       dstream<<"draw_control.blocks_drawn="\r
+                       <<draw_control.blocks_drawn\r
+                       <<", draw_control.blocks_would_have_drawn="\r
+                       <<draw_control.blocks_would_have_drawn\r
+                       <<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
+       draw_control.wanted_min_range = range_min;\r
+       draw_control.wanted_max_blocks = (1.2*draw_control.blocks_drawn)+1;\r
+       \r
+       float block_draw_ratio = 1.0;\r
+       if(draw_control.blocks_would_have_drawn != 0)\r
+       {\r
+               block_draw_ratio = (float)draw_control.blocks_drawn\r
+                       / (float)draw_control.blocks_would_have_drawn;\r
+       }\r
+\r
+       // Calculate the average frametime in the case that all wanted\r
+       // blocks had been drawn\r
+       f32 frametime = added_frametime / added_frames / block_draw_ratio;\r
+       \r
        added_frametime = 0.0;\r
        added_frames = 0;\r
        \r
@@ -1007,7 +1010,7 @@ void updateViewingRange(f32 frametime_in, Client *client)
                return;\r
        }\r
 \r
-       float range = g_viewing_range_nodes;\r
+       float range = draw_control.wanted_range;\r
        float new_range = range;\r
 \r
        static s16 range_old = 0;\r
@@ -1029,16 +1032,24 @@ void updateViewingRange(f32 frametime_in, Client *client)
        // 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
+       //float min_time_per_range = 0.0015;\r
+       float min_time_per_range = 0.0010;\r
+       //float min_time_per_range = 0.05 / range;\r
        if(time_per_range < min_time_per_range)\r
+       {\r
                time_per_range = min_time_per_range;\r
-       \r
-       dstream<<"time_per_range="<<time_per_range<<std::endl;\r
+               dstream<<"time_per_range="<<time_per_range<<" (min)"<<std::endl;\r
+       }\r
+       else\r
+       {\r
+               dstream<<"time_per_range="<<time_per_range<<std::endl;\r
+       }\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
+       //wanted_range_change *= 0.75;\r
+       wanted_range_change *= 0.5;\r
        dstream<<"wanted_range_change="<<wanted_range_change<<std::endl;\r
 \r
        // If needed range change is very small, just return\r
@@ -1051,9 +1062,6 @@ void updateViewingRange(f32 frametime_in, Client *client)
        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
@@ -1065,9 +1073,7 @@ void updateViewingRange(f32 frametime_in, Client *client)
        else\r
                dstream<<std::endl;\r
 \r
-       JMutexAutoLock lock(g_range_mutex);\r
-\r
-       g_viewing_range_nodes = new_range;\r
+       draw_control.wanted_range = new_range;\r
 \r
        range_old = new_range;\r
        frametime_old = frametime;\r
@@ -1324,6 +1330,7 @@ int main(int argc, char *argv[])
 \r
        // Initialize random seed\r
        srand(time(0));\r
+       mysrand(time(0));\r
 \r
        /*\r
                Run unit tests\r
@@ -1334,12 +1341,6 @@ int main(int argc, char *argv[])
                run_tests();\r
        }\r
        \r
-       /*\r
-               Global range mutex\r
-       */\r
-       g_range_mutex.Init();\r
-       assert(g_range_mutex.IsInitialized());\r
-\r
        // Read map parameters from settings\r
 \r
        HMParams hm_params;\r
@@ -1584,10 +1585,7 @@ int main(int argc, char *argv[])
                Create client\r
        */\r
 \r
-       Client client(device, playername,\r
-                       g_range_mutex,\r
-                       g_viewing_range_nodes,\r
-                       g_viewing_range_all);\r
+       Client client(device, playername, draw_control);\r
                        \r
        g_client = &client;\r
        \r
@@ -2409,8 +2407,8 @@ int main(int argc, char *argv[])
                \r
                if(g_settings.getBool("enable_fog") == true)\r
                {\r
-                       f32 range = g_viewing_range_nodes * BS;\r
-                       if(g_viewing_range_all)\r
+                       f32 range = draw_control.wanted_range * BS;\r
+                       if(draw_control.range_all)\r
                                range = 100000*BS;\r
 \r
                        driver->setFog(\r
@@ -2435,13 +2433,13 @@ int main(int argc, char *argv[])
                        wchar_t temptext[150];\r
 \r
                        static float drawtime_avg = 0;\r
-                       drawtime_avg = drawtime_avg * 0.98 + (float)drawtime*0.02;\r
+                       drawtime_avg = drawtime_avg * 0.95 + (float)drawtime*0.05;\r
                        static float beginscenetime_avg = 0;\r
-                       beginscenetime_avg = beginscenetime_avg * 0.98 + (float)beginscenetime*0.02;\r
+                       beginscenetime_avg = beginscenetime_avg * 0.95 + (float)beginscenetime*0.05;\r
                        static float scenetime_avg = 0;\r
-                       scenetime_avg = scenetime_avg * 0.98 + (float)scenetime*0.02;\r
+                       scenetime_avg = scenetime_avg * 0.95 + (float)scenetime*0.05;\r
                        static float endscenetime_avg = 0;\r
-                       endscenetime_avg = endscenetime_avg * 0.98 + (float)endscenetime*0.02;\r
+                       endscenetime_avg = endscenetime_avg * 0.95 + (float)endscenetime*0.05;\r
                        \r
                        swprintf(temptext, 150, L"Minetest-c55 ("\r
                                        L"F: item=%i"\r
@@ -2449,7 +2447,7 @@ int main(int argc, char *argv[])
                                        L")"\r
                                        L" drawtime=%.0f, beginscenetime=%.0f, scenetime=%.0f, endscenetime=%.0f",\r
                                        g_selected_item,\r
-                                       g_viewing_range_all,\r
+                                       draw_control.range_all,\r
                                        drawtime_avg,\r
                                        beginscenetime_avg,\r
                                        scenetime_avg,\r
@@ -2472,7 +2470,7 @@ int main(int argc, char *argv[])
                                        busytime_jitter1_min_sample,\r
                                        busytime_jitter1_max_sample,\r
                                        dtime_jitter1_max_fraction * 100.0,\r
-                                       g_viewing_range_nodes\r
+                                       draw_control.wanted_range\r
                                        );\r
 \r
                        guitext2->setText(temptext);\r
index d5a61d408f0c49d4101d4b774ecb96168b5bc4ee..b092e1fa538780dcfc656cd2d47246a4b6f52c83 100644 (file)
@@ -2889,9 +2889,7 @@ void ServerMap::PrintInfo(std::ostream &out)
 
 ClientMap::ClientMap(
                Client *client,
-               JMutex &range_mutex,
-               float &viewing_range_nodes,
-               bool &viewing_range_all,
+               MapDrawControl &control,
                scene::ISceneNode* parent,
                scene::ISceneManager* mgr,
                s32 id
@@ -2900,9 +2898,7 @@ ClientMap::ClientMap(
        scene::ISceneNode(parent, mgr, id),
        m_client(client),
        mesh(NULL),
-       m_range_mutex(range_mutex),
-       m_viewing_range_nodes(viewing_range_nodes),
-       m_viewing_range_all(viewing_range_all)
+       m_control(control)
 {
        mesh_mutex.Init();
 
@@ -3003,24 +2999,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
        */
        int time1 = time(0);
 
-       //s32 daynight_i = m_client->getDayNightIndex();
        u32 daynight_ratio = m_client->getDayNightRatio();
 
-       /*
-               Collect all blocks that are in the view range
-
-               Should not optimize more here as we want to auto-update
-               all changed nodes in viewing range at the next step.
-       */
-
-       float viewing_range_nodes;
-       bool viewing_range_all;
-       {
-               JMutexAutoLock lock(m_range_mutex);
-               viewing_range_nodes = m_viewing_range_nodes;
-               viewing_range_all = m_viewing_range_all;
-       }
-
        m_camera_mutex.Lock();
        v3f camera_position = m_camera_position;
        v3f camera_direction = m_camera_direction;
@@ -3035,7 +3015,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        camera_position.Y / BS,
                        camera_position.Z / BS);
 
-       v3s16 box_nodes_d = viewing_range_nodes * v3s16(1,1,1);
+       v3s16 box_nodes_d = m_control.wanted_range * v3s16(1,1,1);
 
        v3s16 p_nodes_min = cam_pos_nodes - box_nodes_d;
        v3s16 p_nodes_max = cam_pos_nodes + box_nodes_d;
@@ -3054,12 +3034,14 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
        
        // For limiting number of mesh updates per frame
        u32 mesh_update_count = 0;
+       
+       u32 blocks_would_have_drawn = 0;
+       u32 blocks_drawn = 0;
 
        //NOTE: The sectors map should be locked but we're not doing it
        // because it'd cause too much delays
 
        int timecheck_counter = 0;
-
        core::map<v2s16, MapSector*>::Iterator si;
        si = m_sectors.getIterator();
        for(; si.atEnd() == false; si++)
@@ -3082,7 +3064,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                MapSector *sector = si.getNode()->getValue();
                v2s16 sp = sector->getPos();
                
-               if(viewing_range_all == false)
+               if(m_control.range_all == false)
                {
                        if(sp.X < p_blocks_min.X
                        || sp.X > p_blocks_max.X
@@ -3126,12 +3108,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        // Total distance
                        f32 d = blockpos_relative.getLength();
                        
-                       if(viewing_range_all == false)
+                       if(m_control.range_all == false)
                        {
                                // If block is far away, don't draw it
-                               if(d > viewing_range_nodes * BS)
+                               if(d > m_control.wanted_range * BS)
                                // This is nicer when fog is used
-                               //if((dforward+d)/2 > viewing_range_nodes * BS)
+                               //if((dforward+d)/2 > m_control.wanted_range * BS)
                                        continue;
                        }
                        
@@ -3175,7 +3157,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        }
 
                        f32 faraway = BS*50;
-                       //f32 faraway = viewing_range_nodes * BS;
+                       //f32 faraway = m_control.wanted_range * BS;
                        
                        /*
                                This has to be done with the mesh_mutex unlocked
@@ -3217,6 +3199,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
 
                                if(mesh == NULL)
                                        continue;
+                               
+                               blocks_would_have_drawn++;
+                               if(blocks_drawn >= m_control.wanted_max_blocks
+                                               && m_control.range_all == false
+                                               && d > m_control.wanted_min_range * BS)
+                                       continue;
+                               blocks_drawn++;
 
                                u32 c = mesh->getMeshBufferCount();
 
@@ -3238,6 +3227,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
                        }
                } // foreach sectorblocks
        }
+       
+       m_control.blocks_drawn = blocks_drawn;
+       m_control.blocks_would_have_drawn = blocks_would_have_drawn;
 
        /*dstream<<"renderMap(): is_transparent_pass="<<is_transparent_pass
                        <<", rendered "<<vertex_count<<" vertices."<<std::endl;*/
index 8952bc1108faae56aab8a99afe9feace4da14b53..d4b790abf4739ed68aa38991cf04096d93190bca 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -543,6 +543,31 @@ private:
 
 #ifndef SERVER
 
+struct MapDrawControl
+{
+       MapDrawControl():
+               range_all(false),
+               wanted_range(50),
+               wanted_max_blocks(0),
+               wanted_min_range(0),
+               blocks_drawn(0),
+               blocks_would_have_drawn(0)
+       {
+       }
+       // Overrides limits by drawing everything
+       bool range_all;
+       // Wanted drawing range
+       float wanted_range;
+       // Maximum number of blocks to draw
+       u32 wanted_max_blocks;
+       // Blocks in this range are drawn regardless of number of blocks drawn
+       float wanted_min_range;
+       // Number of blocks rendered is written here by the renderer
+       u32 blocks_drawn;
+       // Number of blocks that would have been drawn in wanted_range
+       u32 blocks_would_have_drawn;
+};
+
 class Client;
 
 class ClientMap : public Map, public scene::ISceneNode
@@ -550,9 +575,7 @@ class ClientMap : public Map, public scene::ISceneNode
 public:
        ClientMap(
                        Client *client,
-                       JMutex &range_mutex,
-                       float &viewing_range_nodes,
-                       bool &viewing_range_all,
+                       MapDrawControl &control,
                        scene::ISceneNode* parent,
                        scene::ISceneManager* mgr,
                        s32 id
@@ -618,10 +641,8 @@ private:
        // This is the master heightmap mesh
        scene::SMesh *mesh;
        JMutex mesh_mutex;
-
-       JMutex &m_range_mutex;
-       float &m_viewing_range_nodes;
-       bool &m_viewing_range_all;
+       
+       MapDrawControl &m_control;
 };
 
 #endif
index 9a35a4b0e1f92f2bcbfc6d07f579e22462e9e295..594f7f4a236c8657bc7f71f89b363dd366d14da0 100644 (file)
@@ -239,6 +239,7 @@ int main(int argc, char *argv[])
 
        // Initialize random seed
        srand(time(0));
+       mysrand(time(0));
 
        /*
                Run unit tests
index 7126cbbdc57a3f2bdcaa2335d4977c1388560cbe..924324b90a8c4ff38cc9f4b6e3aad9eb397f4925 100644 (file)
@@ -88,4 +88,18 @@ const v3s16 g_26dirs[26] =
        // 26
 };
 
+static unsigned long next = 1;
+
+/* RAND_MAX assumed to be 32767 */
+int myrand(void)
+{
+   next = next * 1103515245 + 12345;
+   return((unsigned)(next/65536) % 32768);
+}
+
+void mysrand(unsigned seed)
+{
+   next = seed;
+}
+
 
index 3764616d09373370e1873ec8d49f5552ae2a1ee5..008a95c3834c5c3f75e513056f16fa3f65b6d377 100644 (file)
@@ -1323,5 +1323,10 @@ private:
        MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
 };
 
+// Pseudo-random (VC++ rand() sucks)
+int myrand(void);
+void mysrand(unsigned seed);
+#define MYRAND_MAX 32767
+
 #endif