+
+ m_control.blocks_would_have_drawn = blocks_would_have_drawn;
+ m_control.blocks_drawn = blocks_drawn;
+ m_control.farthest_drawn = farthest_drawn;
+
+ g_profiler->avg("CM: blocks in range", blocks_in_range);
+ g_profiler->avg("CM: blocks occlusion culled", blocks_occlusion_culled);
+ if(blocks_in_range != 0)
+ g_profiler->avg("CM: blocks in range without mesh (frac)",
+ (float)blocks_in_range_without_mesh/blocks_in_range);
+ g_profiler->avg("CM: blocks drawn", blocks_drawn);
+ g_profiler->avg("CM: farthest drawn", farthest_drawn);
+ g_profiler->avg("CM: wanted max blocks", m_control.wanted_max_blocks);
+}
+
+struct MeshBufList
+{
+ video::SMaterial m;
+ std::list<scene::IMeshBuffer*> bufs;
+};
+
+struct MeshBufListList
+{
+ std::list<MeshBufList> lists;
+
+ void clear()
+ {
+ lists.clear();
+ }
+
+ void add(scene::IMeshBuffer *buf)
+ {
+ for(std::list<MeshBufList>::iterator i = lists.begin();
+ i != lists.end(); ++i){
+ MeshBufList &l = *i;
+ video::SMaterial &m = buf->getMaterial();
+
+ // comparing a full material is quite expensive so we don't do it if
+ // not even first texture is equal
+ if (l.m.TextureLayer[0].Texture != m.TextureLayer[0].Texture)
+ continue;
+
+ if (l.m == m) {
+ l.bufs.push_back(buf);
+ return;
+ }
+ }
+ MeshBufList l;
+ l.m = buf->getMaterial();
+ l.bufs.push_back(buf);
+ lists.push_back(l);
+ }
+};
+
+void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
+{
+ DSTACK(__FUNCTION_NAME);
+
+ bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
+
+ std::string prefix;
+ if(pass == scene::ESNRP_SOLID)
+ prefix = "CM: solid: ";
+ else
+ prefix = "CM: transparent: ";
+
+ /*
+ This is called two times per frame, reset on the non-transparent one
+ */
+ if(pass == scene::ESNRP_SOLID)
+ {
+ m_last_drawn_sectors.clear();
+ }
+
+ bool use_trilinear_filter = g_settings->getBool("trilinear_filter");
+ bool use_bilinear_filter = g_settings->getBool("bilinear_filter");
+ bool use_anisotropic_filter = g_settings->getBool("anisotropic_filter");
+
+ /*
+ Get time for measuring timeout.
+
+ Measuring time is very useful for long delays when the
+ machine is swapping a lot.
+ */
+ int time1 = time(0);
+
+ /*
+ Get animation parameters
+ */
+ float animation_time = m_client->getAnimationTime();
+ int crack = m_client->getCrackLevel();
+ u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
+
+ m_camera_mutex.Lock();
+ v3f camera_position = m_camera_position;
+ v3f camera_direction = m_camera_direction;
+ f32 camera_fov = m_camera_fov;
+ m_camera_mutex.Unlock();
+
+ /*
+ Get all blocks and draw all visible ones
+ */
+
+ v3s16 cam_pos_nodes = floatToInt(camera_position, BS);
+
+ 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;
+
+ // Take a fair amount as we will be dropping more out later
+ // Umm... these additions are a bit strange but they are needed.
+ v3s16 p_blocks_min(
+ p_nodes_min.X / MAP_BLOCKSIZE - 3,
+ p_nodes_min.Y / MAP_BLOCKSIZE - 3,
+ p_nodes_min.Z / MAP_BLOCKSIZE - 3);
+ v3s16 p_blocks_max(
+ p_nodes_max.X / MAP_BLOCKSIZE + 1,
+ p_nodes_max.Y / MAP_BLOCKSIZE + 1,
+ p_nodes_max.Z / MAP_BLOCKSIZE + 1);
+
+ u32 vertex_count = 0;
+ u32 meshbuffer_count = 0;
+
+ // For limiting number of mesh animations per frame
+ u32 mesh_animate_count = 0;
+ u32 mesh_animate_count_far = 0;
+
+ // Blocks that were drawn and had a mesh
+ u32 blocks_drawn = 0;
+ // Blocks which had a corresponding meshbuffer for this pass
+ u32 blocks_had_pass_meshbuf = 0;
+ // Blocks from which stuff was actually drawn
+ u32 blocks_without_stuff = 0;
+