Mapblock_mesh_generate_special: Improve performance
authorparamat <mat.gregory@virginmedia.com>
Sun, 2 Oct 2016 23:56:17 +0000 (00:56 +0100)
committerparamat <mat.gregory@virginmedia.com>
Mon, 3 Oct 2016 23:06:28 +0000 (00:06 +0100)
Remove uses of std::map.
Make sure we use ContentFeatures reference not value.
Original commit by gregorycu.

src/content_mapblock.cpp

index 173649aee7f50a4c2552604da382c7aa9b094731..8ce0f1e0af5d4cdd33c76bbedd28c9ec13241fcf 100644 (file)
@@ -172,6 +172,15 @@ static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
                *neighbors |= v;
 }
 
+// For use in mapblock_mesh_generate_special
+// X,Y,Z of position must be -1,0,1
+// This expression is a simplification of
+// 3 * 3 * (pos.X + 1) + 3 * (pos.Y + 1) + (pos.Z + 1)
+static inline int NeighborToIndex(const v3s16 &pos)
+{
+       return 9 * pos.X + 3 * pos.Y + pos.Z + 13;
+}
+
 /*
        TODO: Fix alpha blending for special nodes
        Currently only the last element rendered is blended correct
@@ -401,9 +410,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 
                        // Neighbor liquid levels (key = relative position)
                        // Includes current node
-                       std::map<v3s16, f32> neighbor_levels;
-                       std::map<v3s16, content_t> neighbor_contents;
-                       std::map<v3s16, u8> neighbor_flags;
+
+                       struct NeighborData {
+                               f32 level;
+                               content_t content;
+                               u8 flags;
+                       };
+                       NeighborData neighbor_data_matrix[27];
+
                        const u8 neighborflag_top_is_same_liquid = 0x01;
                        v3s16 neighbor_dirs[9] = {
                                v3s16(0,0,0),
@@ -449,9 +463,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                                flags |= neighborflag_top_is_same_liquid;
                                }
 
-                               neighbor_levels[neighbor_dirs[i]] = level;
-                               neighbor_contents[neighbor_dirs[i]] = content;
-                               neighbor_flags[neighbor_dirs[i]] = flags;
+                               NeighborData &neighbor_data =
+                                       neighbor_data_matrix[NeighborToIndex(neighbor_dirs[i])];
+
+                               neighbor_data.level = level;
+                               neighbor_data.content = content;
+                               neighbor_data.flags = flags;
                        }
 
                        // Corner heights (average between four liquids)
@@ -472,10 +489,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                for(u32 j=0; j<4; j++)
                                {
                                        v3s16 neighbordir = cornerdir - halfdirs[j];
-                                       content_t content = neighbor_contents[neighbordir];
+
+                                       NeighborData &neighbor_data =
+                                               neighbor_data_matrix[NeighborToIndex(neighbordir)];
+                                       content_t content = neighbor_data.content;
                                        // If top is liquid, draw starting from top of node
-                                       if(neighbor_flags[neighbordir] &
-                                                       neighborflag_top_is_same_liquid)
+                                       if (neighbor_data.flags & neighborflag_top_is_same_liquid)
                                        {
                                                cornerlevel = 0.5*BS;
                                                valid_count = 1;
@@ -491,7 +510,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                        // Flowing liquid has level information
                                        else if(content == c_flowing)
                                        {
-                                               cornerlevel += neighbor_levels[neighbordir];
+                                               cornerlevel += neighbor_data.level;
                                                valid_count++;
                                        }
                                        else if(content == CONTENT_AIR)
@@ -526,15 +545,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        {
                                v3s16 dir = side_dirs[i];
 
+                               NeighborData& neighbor_data =
+                                       neighbor_data_matrix[NeighborToIndex(dir)];
                                /*
                                        If our topside is liquid and neighbor's topside
                                        is liquid, don't draw side face
                                */
-                               if(top_is_same_liquid &&
-                                               neighbor_flags[dir] & neighborflag_top_is_same_liquid)
+                               if (top_is_same_liquid &&
+                                               neighbor_data.flags & neighborflag_top_is_same_liquid)
                                        continue;
 
-                               content_t neighbor_content = neighbor_contents[dir];
+                               content_t neighbor_content = neighbor_data.content;
                                const ContentFeatures &n_feat = nodedef->get(neighbor_content);
 
                                // Don't draw face if neighbor is blocking the view
@@ -1506,8 +1527,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                                continue;
                                        MapNode n_xy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x + xz, y + y0, z));
                                        MapNode n_zy = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x, y + y0, z + xz));
-                                       ContentFeatures def_xy = nodedef->get(n_xy);
-                                       ContentFeatures def_zy = nodedef->get(n_zy);
+                                       const ContentFeatures &def_xy = nodedef->get(n_xy);
+                                       const ContentFeatures &def_zy = nodedef->get(n_zy);
 
                                        // Check if current node would connect with the rail
                                        is_rail_x[index] = ((def_xy.drawtype == NDT_RAILLIKE