Add warning when disabling secure.enable_security (#9943)
[oweals/minetest.git] / src / client / mapblock_mesh.cpp
index ed8a073de5792bbc92464b8f2ff820c3327f6773..1020e35f5f86df0c191e561063e568d07f6a54f4 100644 (file)
@@ -225,7 +225,7 @@ static u16 getSmoothLightCombined(const v3s16 &p,
                return f.light_propagates;
        };
 
-       std::array<bool, 4> obstructed = {{ 1, 1, 1, 1 }};
+       bool obstructed[4] = { true, true, true, true };
        add_node(0);
        bool opaque1 = !add_node(1);
        bool opaque2 = !add_node(2);
@@ -372,6 +372,32 @@ void final_color_blend(video::SColor *result,
        Mesh generation helpers
 */
 
+// This table is moved outside getNodeVertexDirs to avoid the compiler using
+// a mutex to initialize this table at runtime right in the hot path.
+// For details search the internet for "cxa_guard_acquire".
+static const v3s16 vertex_dirs_table[] = {
+       // ( 1, 0, 0)
+       v3s16( 1,-1, 1), v3s16( 1,-1,-1),
+       v3s16( 1, 1,-1), v3s16( 1, 1, 1),
+       // ( 0, 1, 0)
+       v3s16( 1, 1,-1), v3s16(-1, 1,-1),
+       v3s16(-1, 1, 1), v3s16( 1, 1, 1),
+       // ( 0, 0, 1)
+       v3s16(-1,-1, 1), v3s16( 1,-1, 1),
+       v3s16( 1, 1, 1), v3s16(-1, 1, 1),
+       // invalid
+       v3s16(), v3s16(), v3s16(), v3s16(),
+       // ( 0, 0,-1)
+       v3s16( 1,-1,-1), v3s16(-1,-1,-1),
+       v3s16(-1, 1,-1), v3s16( 1, 1,-1),
+       // ( 0,-1, 0)
+       v3s16( 1,-1, 1), v3s16(-1,-1, 1),
+       v3s16(-1,-1,-1), v3s16( 1,-1,-1),
+       // (-1, 0, 0)
+       v3s16(-1,-1,-1), v3s16(-1,-1, 1),
+       v3s16(-1, 1, 1), v3s16(-1, 1,-1)
+};
+
 /*
        vertex_dirs: v3s16[4]
 */
@@ -384,44 +410,16 @@ static void getNodeVertexDirs(const v3s16 &dir, v3s16 *vertex_dirs)
                2: top-left
                3: top-right
        */
-       if (dir == v3s16(0, 0, 1)) {
-               // If looking towards z+, this is the face that is behind
-               // the center point, facing towards z+.
-               vertex_dirs[0] = v3s16(-1,-1, 1);
-               vertex_dirs[1] = v3s16( 1,-1, 1);
-               vertex_dirs[2] = v3s16( 1, 1, 1);
-               vertex_dirs[3] = v3s16(-1, 1, 1);
-       } else if (dir == v3s16(0, 0, -1)) {
-               // faces towards Z-
-               vertex_dirs[0] = v3s16( 1,-1,-1);
-               vertex_dirs[1] = v3s16(-1,-1,-1);
-               vertex_dirs[2] = v3s16(-1, 1,-1);
-               vertex_dirs[3] = v3s16( 1, 1,-1);
-       } else if (dir == v3s16(1, 0, 0)) {
-               // faces towards X+
-               vertex_dirs[0] = v3s16( 1,-1, 1);
-               vertex_dirs[1] = v3s16( 1,-1,-1);
-               vertex_dirs[2] = v3s16( 1, 1,-1);
-               vertex_dirs[3] = v3s16( 1, 1, 1);
-       } else if (dir == v3s16(-1, 0, 0)) {
-               // faces towards X-
-               vertex_dirs[0] = v3s16(-1,-1,-1);
-               vertex_dirs[1] = v3s16(-1,-1, 1);
-               vertex_dirs[2] = v3s16(-1, 1, 1);
-               vertex_dirs[3] = v3s16(-1, 1,-1);
-       } else if (dir == v3s16(0, 1, 0)) {
-               // faces towards Y+ (assume Z- as "down" in texture)
-               vertex_dirs[0] = v3s16( 1, 1,-1);
-               vertex_dirs[1] = v3s16(-1, 1,-1);
-               vertex_dirs[2] = v3s16(-1, 1, 1);
-               vertex_dirs[3] = v3s16( 1, 1, 1);
-       } else if (dir == v3s16(0, -1, 0)) {
-               // faces towards Y- (assume Z+ as "down" in texture)
-               vertex_dirs[0] = v3s16( 1,-1, 1);
-               vertex_dirs[1] = v3s16(-1,-1, 1);
-               vertex_dirs[2] = v3s16(-1,-1,-1);
-               vertex_dirs[3] = v3s16( 1,-1,-1);
-       }
+
+       // Direction must be (1,0,0), (-1,0,0), (0,1,0), (0,-1,0),
+       // (0,0,1), (0,0,-1)
+       assert(dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z == 1);
+
+       // Convert direction to single integer for table lookup
+       u8 idx = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7;
+       idx = (idx - 1) * 4;
+
+       memcpy(vertex_dirs, &vertex_dirs_table[idx], 4 * sizeof(v3s16));
 }
 
 static void getNodeTextureCoords(v3f base, const v3f &scale, const v3s16 &dir, float *u, float *v)
@@ -744,7 +742,7 @@ void getNodeTile(MapNode mn, const v3s16 &p, const v3s16 &dir, MeshMakeData *dat
        u8 dir_i = ((dir.X + 2 * dir.Y + 3 * dir.Z) & 7) * 2;
 
        // Get rotation for things like chests
-       u8 facedir = mn.getFaceDir(ndef);
+       u8 facedir = mn.getFaceDir(ndef, true);
 
        static const u16 dir_to_tile[24 * 16] =
        {
@@ -795,6 +793,7 @@ static void getTileInfo(
                v3s16 &p_corrected,
                v3s16 &face_dir_corrected,
                u16 *lights,
+               u8 &waving,
                TileSpec &tile
        )
 {
@@ -842,6 +841,7 @@ static void getTileInfo(
 
        getNodeTile(n, p_corrected, face_dir_corrected, data, tile);
        const ContentFeatures &f = ndef->get(n);
+       waving = f.waving;
        tile.emissive_light = f.light_source;
 
        // eg. water and glass
@@ -876,6 +876,10 @@ static void updateFastFaceRow(
                const v3s16 &&face_dir,
                std::vector<FastFace> &dest)
 {
+       static thread_local const bool waving_liquids =
+               g_settings->getBool("enable_shaders") &&
+               g_settings->getBool("enable_waving_water");
+
        v3s16 p = startpos;
 
        u16 continuous_tiles_count = 1;
@@ -884,10 +888,13 @@ static void updateFastFaceRow(
        v3s16 p_corrected;
        v3s16 face_dir_corrected;
        u16 lights[4] = {0, 0, 0, 0};
+       u8 waving = 0;
        TileSpec tile;
+
+       // Get info of first tile
        getTileInfo(data, p, face_dir,
                        makes_face, p_corrected, face_dir_corrected,
-                       lights, tile);
+                       lights, waving, tile);
 
        // Unroll this variable which has a significant build cost
        TileSpec next_tile;
@@ -895,8 +902,6 @@ static void updateFastFaceRow(
                // If tiling can be done, this is set to false in the next step
                bool next_is_different = true;
 
-               v3s16 p_next;
-
                bool next_makes_face = false;
                v3s16 next_p_corrected;
                v3s16 next_face_dir_corrected;
@@ -905,17 +910,20 @@ static void updateFastFaceRow(
                // If at last position, there is nothing to compare to and
                // the face must be drawn anyway
                if (j != MAP_BLOCKSIZE - 1) {
-                       p_next = p + translate_dir;
+                       p += translate_dir;
 
-                       getTileInfo(data, p_next, face_dir,
+                       getTileInfo(data, p, face_dir,
                                        next_makes_face, next_p_corrected,
                                        next_face_dir_corrected, next_lights,
+                                       waving,
                                        next_tile);
 
                        if (next_makes_face == makes_face
                                        && next_p_corrected == p_corrected + translate_dir
                                        && next_face_dir_corrected == face_dir_corrected
-                                       && memcmp(next_lights, lights, ARRLEN(lights) * sizeof(u16)) == 0
+                                       && memcmp(next_lights, lights, sizeof(lights)) == 0
+                                       // Don't apply fast faces to waving water.
+                                       && (waving != 3 || !waving_liquids)
                                        && next_tile.isTileable(tile)) {
                                next_is_different = false;
                                continuous_tiles_count++;
@@ -942,10 +950,7 @@ static void updateFastFaceRow(
 
                                makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
                                                pf, sp, face_dir_corrected, scale, dest);
-
-                               g_profiler->avg("Meshgen: faces drawn by tiling", 0);
-                               for (int i = 1; i < continuous_tiles_count; i++)
-                                       g_profiler->avg("Meshgen: faces drawn by tiling", 1);
+                               g_profiler->avg("Meshgen: Tiles per face [#]", continuous_tiles_count);
                        }
 
                        continuous_tiles_count = 1;
@@ -954,10 +959,9 @@ static void updateFastFaceRow(
                makes_face = next_makes_face;
                p_corrected = next_p_corrected;
                face_dir_corrected = next_face_dir_corrected;
-               std::memcpy(lights, next_lights, ARRLEN(lights) * sizeof(u16));
+               memcpy(lights, next_lights, sizeof(lights));
                if (next_is_different)
-                       tile = next_tile;
-               p = p_next;
+                       tile = std::move(next_tile); // faster than copy
        }
 }