]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/client/mapblock_mesh.cpp
Merge branch 'master' of https://github.com/minetest/minetest
[dragonfireclient.git] / src / client / mapblock_mesh.cpp
index c165438a097b622a3a324f52bec823e3f1c4459f..b7c5ea16a4b709170dd16c500ebe75716a7d3c41 100644 (file)
@@ -35,11 +35,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        MeshMakeData
 */
 
-MeshMakeData::MeshMakeData(Client *client, bool use_shaders,
-               bool use_tangent_vertices):
+MeshMakeData::MeshMakeData(Client *client, bool use_shaders):
        m_client(client),
-       m_use_shaders(use_shaders),
-       m_use_tangent_vertices(use_tangent_vertices)
+       m_use_shaders(use_shaders)
 {}
 
 void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
@@ -81,33 +79,6 @@ void MeshMakeData::fill(MapBlock *block)
        }
 }
 
-void MeshMakeData::fillSingleNode(MapNode *node)
-{
-       m_blockpos = v3s16(0,0,0);
-
-       v3s16 blockpos_nodes = v3s16(0,0,0);
-       VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE,
-                       blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1));
-       s32 volume = area.getVolume();
-       s32 our_node_index = area.index(1,1,1);
-
-       // Allocate this block + neighbors
-       m_vmanip.clear();
-       m_vmanip.addArea(area);
-
-       // Fill in data
-       MapNode *data = new MapNode[volume];
-       for(s32 i = 0; i < volume; i++)
-       {
-               if (i == our_node_index)
-                       data[i] = *node;
-               else
-                       data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0);
-       }
-       m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent());
-       delete[] data;
-}
-
 void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
 {
        if (crack_level >= 0)
@@ -116,7 +87,7 @@ void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
 
 void MeshMakeData::setSmoothLighting(bool smooth_lighting)
 {
-       m_smooth_lighting = smooth_lighting;
+       m_smooth_lighting = smooth_lighting && ! g_settings->getBool("fullbright");
 }
 
 /*
@@ -228,7 +199,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);
@@ -375,6 +346,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]
 */
@@ -387,44 +384,25 @@ 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;
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#if __GNUC__ > 7
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+#endif
+       memcpy(vertex_dirs, &vertex_dirs_table[idx], 4 * sizeof(v3s16));
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
 }
 
 static void getNodeTextureCoords(v3f base, const v3f &scale, const v3s16 &dir, float *u, float *v)
@@ -681,6 +659,7 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
        u8 c1 = f1.solidness;
        u8 c2 = f2.solidness;
 
+
        if (c1 == c2)
                return 0;
 
@@ -689,6 +668,7 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
        else if (c2 == 0)
                c2 = f2.visual_solidness;
 
+
        if (c1 == c2) {
                *equivalent = true;
                // If same solidness, liquid takes precense
@@ -788,6 +768,24 @@ void getNodeTile(MapNode mn, const v3s16 &p, const v3s16 &dir, MeshMakeData *dat
        tile.rotation = tile.world_aligned ? 0 : dir_to_tile[tile_index + 1];
 }
 
+std::set<content_t> splitToContentT(std::string str, const NodeDefManager *ndef)
+{
+       str += "\n";
+       std::set<content_t> dat;
+       std::string buf;
+       for (char c : str) {
+               if (c == ',' || c == '\n') {
+                       if (! buf.empty()) {
+                               dat.insert(ndef->getId(buf));
+                       }
+                       buf.clear();
+               } else if (c != ' ') {
+                       buf += c;
+               }
+       }
+       return dat;
+}
+
 static void getTileInfo(
                // Input:
                MeshMakeData *data,
@@ -799,31 +797,40 @@ static void getTileInfo(
                v3s16 &face_dir_corrected,
                u16 *lights,
                u8 &waving,
-               TileSpec &tile
-       )
+               TileSpec &tile,
+               // lol more Input
+               bool xray,
+               std::set<content_t> xraySet)
 {
        VoxelManipulator &vmanip = data->m_vmanip;
        const NodeDefManager *ndef = data->m_client->ndef();
        v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
-
+       
        const MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p);
 
+       content_t c0 = n0.getContent();
+       if (xray && xraySet.find(c0) != xraySet.end())
+               c0 = CONTENT_AIR;
        // Don't even try to get n1 if n0 is already CONTENT_IGNORE
-       if (n0.getContent() == CONTENT_IGNORE) {
+       if (c0 == CONTENT_IGNORE) {
                makes_face = false;
                return;
        }
 
        const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir);
 
-       if (n1.getContent() == CONTENT_IGNORE) {
+       content_t c1 = n1.getContent();
+       if (xray && xraySet.find(c1) != xraySet.end())
+               c1 = CONTENT_AIR;
+
+       if (c1 == CONTENT_IGNORE) {
                makes_face = false;
                return;
        }
 
        // This is hackish
        bool equivalent = false;
-       u8 mf = face_contents(n0.getContent(), n1.getContent(),
+       u8 mf = face_contents(c0, c1,
                        &equivalent, ndef);
 
        if (mf == 0) {
@@ -879,7 +886,9 @@ static void updateFastFaceRow(
                v3s16 translate_dir,
                const v3f &&translate_dir_f,
                const v3s16 &&face_dir,
-               std::vector<FastFace> &dest)
+               std::vector<FastFace> &dest,
+               bool xray,
+               std::set<content_t> xraySet)
 {
        static thread_local const bool waving_liquids =
                g_settings->getBool("enable_shaders") &&
@@ -893,11 +902,13 @@ static void updateFastFaceRow(
        v3s16 p_corrected;
        v3s16 face_dir_corrected;
        u16 lights[4] = {0, 0, 0, 0};
-       u8 waving;
+       u8 waving = 0;
        TileSpec tile;
+
+       // Get info of first tile
        getTileInfo(data, p, face_dir,
                        makes_face, p_corrected, face_dir_corrected,
-                       lights, waving, tile);
+                       lights, waving, tile, xray, xraySet);
 
        // Unroll this variable which has a significant build cost
        TileSpec next_tile;
@@ -905,8 +916,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;
@@ -915,18 +924,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;
-
-                       getTileInfo(data, p_next, face_dir,
+                       p += translate_dir;
+                       
+                       getTileInfo(data, p, face_dir,
                                        next_makes_face, next_p_corrected,
                                        next_face_dir_corrected, next_lights,
                                        waving,
-                                       next_tile);
-
+                                       next_tile,
+                                       xray,
+                                       xraySet);
+                       
                        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)) {
@@ -964,15 +975,14 @@ 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
        }
 }
 
 static void updateAllFastFaceRows(MeshMakeData *data,
-               std::vector<FastFace> &dest)
+               std::vector<FastFace> &dest, bool xray, std::set<content_t> xraySet)
 {
        /*
                Go through every y,z and get top(y+) faces in rows of x+
@@ -984,7 +994,9 @@ static void updateAllFastFaceRows(MeshMakeData *data,
                                v3s16(1, 0, 0), //dir
                                v3f  (1, 0, 0),
                                v3s16(0, 1, 0), //face dir
-                               dest);
+                               dest,
+                               xray,
+                               xraySet);
 
        /*
                Go through every x,y and get right(x+) faces in rows of z+
@@ -996,7 +1008,9 @@ static void updateAllFastFaceRows(MeshMakeData *data,
                                v3s16(0, 0, 1), //dir
                                v3f  (0, 0, 1),
                                v3s16(1, 0, 0), //face dir
-                               dest);
+                               dest,
+                               xray,
+                               xraySet);
 
        /*
                Go through every y,z and get back(z+) faces in rows of x+
@@ -1008,7 +1022,9 @@ static void updateAllFastFaceRows(MeshMakeData *data,
                                v3s16(1, 0, 0), //dir
                                v3f  (1, 0, 0),
                                v3s16(0, 0, 1), //face dir
-                               dest);
+                               dest,
+                               xray,
+                               xraySet);
 }
 
 static void applyTileColor(PreMeshBuffer &pmb)
@@ -1040,10 +1056,9 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        for (auto &m : m_mesh)
                m = new scene::SMesh();
        m_enable_shaders = data->m_use_shaders;
-       m_use_tangent_vertices = data->m_use_tangent_vertices;
        m_enable_vbo = g_settings->getBool("enable_vbo");
 
-       if (g_settings->getBool("enable_minimap")) {
+       if (data->m_client->getMinimap()) {
                m_minimap_mapblock = new MinimapMapblock;
                m_minimap_mapblock->getMinimapNodes(
                        &data->m_vmanip, data->m_blockpos * MAP_BLOCKSIZE);
@@ -1055,21 +1070,47 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
        std::vector<FastFace> fastfaces_new;
        fastfaces_new.reserve(512);
-
+       /*
+               X-Ray
+       */
+       bool xray = g_settings->getBool("xray");
+       std::set<content_t> xraySet, nodeESPSet;
+       if (xray)
+               xraySet = splitToContentT(g_settings->get("xray_nodes"), data->m_client->ndef());
+       
+       nodeESPSet = splitToContentT(g_settings->get("node_esp_nodes"), data->m_client->ndef());
+       
        /*
                We are including the faces of the trailing edges of the block.
                This means that when something changes, the caller must
                also update the meshes of the blocks at the leading edges.
 
                NOTE: This is the slowest part of this method.
-       */
+       */      
        {
                // 4-23ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
                //TimeTaker timer2("updateAllFastFaceRows()");
-               updateAllFastFaceRows(data, fastfaces_new);
+               updateAllFastFaceRows(data, fastfaces_new, xray, xraySet);
        }
        // End of slow part
 
+       /*
+               NodeESP
+       */
+       {
+               v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
+               for (s16 x = 0; x < MAP_BLOCKSIZE; x++) {
+                       for (s16 y = 0; y < MAP_BLOCKSIZE; y++) {
+                               for (s16 z = 0; z < MAP_BLOCKSIZE; z++) {
+                                       v3s16 pos = v3s16(x, y, z) + blockpos_nodes;
+                                       const MapNode &node = data->m_vmanip.getNodeRefUnsafeCheckFlags(pos);
+                                       if (nodeESPSet.find(node.getContent()) != nodeESPSet.end())
+                                               esp_nodes.insert(pos);
+                               }
+                       }
+               }
+       }
+
        /*
                Convert FastFaces to MeshCollector
        */
@@ -1194,41 +1235,12 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
                        scene::SMesh *mesh = (scene::SMesh *)m_mesh[layer];
 
-                       // Create meshbuffer, add to mesh
-                       if (m_use_tangent_vertices) {
-                               scene::SMeshBufferTangents *buf =
-                                               new scene::SMeshBufferTangents();
-                               buf->Material = material;
-                               buf->Vertices.reallocate(p.vertices.size());
-                               buf->Indices.reallocate(p.indices.size());
-                               for (const video::S3DVertex &v: p.vertices)
-                                       buf->Vertices.push_back(video::S3DVertexTangents(v.Pos, v.Color, v.TCoords));
-                               for (u16 i: p.indices)
-                                       buf->Indices.push_back(i);
-                               buf->recalculateBoundingBox();
-                               mesh->addMeshBuffer(buf);
-                               buf->drop();
-                       } else {
-                               scene::SMeshBuffer *buf = new scene::SMeshBuffer();
-                               buf->Material = material;
-                               buf->append(&p.vertices[0], p.vertices.size(),
-                                       &p.indices[0], p.indices.size());
-                               mesh->addMeshBuffer(buf);
-                               buf->drop();
-                       }
-               }
-
-               /*
-                       Do some stuff to the mesh
-               */
-               m_camera_offset = camera_offset;
-               translateMesh(m_mesh[layer],
-                       intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
-
-               if (m_use_tangent_vertices) {
-                       scene::IMeshManipulator* meshmanip =
-                               RenderingEngine::get_scene_manager()->getMeshManipulator();
-                       meshmanip->recalculateTangents(m_mesh[layer], true, false, false);
+                       scene::SMeshBuffer *buf = new scene::SMeshBuffer();
+                       buf->Material = material;
+                       buf->append(&p.vertices[0], p.vertices.size(),
+                               &p.indices[0], p.indices.size());
+                       mesh->addMeshBuffer(buf);
+                       buf->drop();
                }
 
                if (m_mesh[layer]) {
@@ -1257,13 +1269,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 MapBlockMesh::~MapBlockMesh()
 {
        for (scene::IMesh *m : m_mesh) {
-               if (m_enable_vbo && m)
+               if (m_enable_vbo) {
                        for (u32 i = 0; i < m->getMeshBufferCount(); i++) {
                                scene::IMeshBuffer *buf = m->getMeshBuffer(i);
                                RenderingEngine::get_video_driver()->removeHardwareBuffer(buf);
                        }
+               }
                m->drop();
-               m = NULL;
        }
        delete m_minimap_mapblock;
 }
@@ -1357,19 +1369,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
        return true;
 }
 
-void MapBlockMesh::updateCameraOffset(v3s16 camera_offset)
-{
-       if (camera_offset != m_camera_offset) {
-               for (scene::IMesh *layer : m_mesh) {
-                       translateMesh(layer,
-                               intToFloat(m_camera_offset - camera_offset, BS));
-                       if (m_enable_vbo)
-                               layer->setDirty();
-               }
-               m_camera_offset = camera_offset;
-       }
-}
-
 video::SColor encode_light(u16 light, u8 emissive_light)
 {
        // Get components