]> git.lizzy.rs Git - minetest.git/blobdiff - src/client/mapblock_mesh.cpp
Fix a -Wreorder warning
[minetest.git] / src / client / mapblock_mesh.cpp
index 965dd5e2954af2f9adf0162dde57240a20ef9d8e..f5abd2777d4894437086d59eb4a1ca58ab822a26 100644 (file)
@@ -37,6 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 MeshMakeData::MeshMakeData(Client *client, bool use_shaders):
+       m_mesh_grid(client->getMeshGrid()),
+       side_length(MAP_BLOCKSIZE * m_mesh_grid.cell_size),
        m_client(client),
        m_use_shaders(use_shaders)
 {}
@@ -49,37 +51,19 @@ void MeshMakeData::fillBlockDataBegin(const v3s16 &blockpos)
 
        m_vmanip.clear();
        VoxelArea voxel_area(blockpos_nodes - v3s16(1,1,1) * MAP_BLOCKSIZE,
-                       blockpos_nodes + v3s16(1,1,1) * MAP_BLOCKSIZE*2-v3s16(1,1,1));
+                       blockpos_nodes + v3s16(1,1,1) * (side_length + MAP_BLOCKSIZE /* extra layer of blocks around the mesh */) - v3s16(1,1,1));
        m_vmanip.addArea(voxel_area);
 }
 
-void MeshMakeData::fillBlockData(const v3s16 &block_offset, MapNode *data)
+void MeshMakeData::fillBlockData(const v3s16 &bp, MapNode *data)
 {
        v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
        VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));
 
-       v3s16 bp = m_blockpos + block_offset;
        v3s16 blockpos_nodes = bp * MAP_BLOCKSIZE;
        m_vmanip.copyFrom(data, data_area, v3s16(0,0,0), blockpos_nodes, data_size);
 }
 
-void MeshMakeData::fill(MapBlock *block)
-{
-       fillBlockDataBegin(block->getPos());
-
-       fillBlockData(v3s16(0,0,0), block->getData());
-
-       // Get map for reading neighbor blocks
-       Map *map = block->getParent();
-
-       for (const v3s16 &dir : g_26dirs) {
-               v3s16 bp = m_blockpos + dir;
-               MapBlock *b = map->getBlockNoCreateNoEx(bp);
-               if(b)
-                       fillBlockData(dir, b->getData());
-       }
-}
-
 void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
 {
        if (crack_level >= 0)
@@ -102,9 +86,8 @@ void MeshMakeData::setSmoothLighting(bool smooth_lighting)
 static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
        const NodeDefManager *ndef)
 {
-       u8 light = n.getLight(bank, ndef);
-       if (light > 0)
-               light = rangelim(light + increment, 0, LIGHT_SUN);
+       u8 light = n.getLight(bank, ndef->getLightingFlags(n));
+       light = rangelim(light + increment, 0, LIGHT_SUN);
        return decode_light(light);
 }
 
@@ -126,17 +109,19 @@ u16 getInteriorLight(MapNode n, s32 increment, const NodeDefManager *ndef)
 static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
        v3s16 face_dir, const NodeDefManager *ndef)
 {
+       ContentLightingFlags f1 = ndef->getLightingFlags(n);
+       ContentLightingFlags f2 = ndef->getLightingFlags(n2);
+
        u8 light;
-       u8 l1 = n.getLight(bank, ndef);
-       u8 l2 = n2.getLight(bank, ndef);
+       u8 l1 = n.getLight(bank, f1);
+       u8 l2 = n2.getLight(bank, f2);
        if(l1 > l2)
                light = l1;
        else
                light = l2;
 
        // Boost light level for light sources
-       u8 light_source = MYMAX(ndef->get(n).light_source,
-                       ndef->get(n2).light_source);
+       u8 light_source = MYMAX(f1.light_source, f2.light_source);
        if(light_source > light)
                light = light_source;
 
@@ -184,8 +169,8 @@ static u16 getSmoothLightCombined(const v3s16 &p,
                        light_source_max = f.light_source;
                // Check f.solidness because fast-style leaves look better this way
                if (f.param_type == CPT_LIGHT && f.solidness != 2) {
-                       u8 light_level_day = n.getLightNoChecks(LIGHTBANK_DAY, &f);
-                       u8 light_level_night = n.getLightNoChecks(LIGHTBANK_NIGHT, &f);
+                       u8 light_level_day = n.getLight(LIGHTBANK_DAY, f.getLightingFlags());
+                       u8 light_level_night = n.getLight(LIGHTBANK_NIGHT, f.getLightingFlags());
                        if (light_level_day == LIGHT_SUN)
                                direct_sunlight = true;
                        light_day += decode_light(light_level_day);
@@ -651,7 +636,7 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
        const ContentFeatures &f2 = ndef->get(m2);
 
        // Contents don't differ for different forms of same liquid
-       if (f1.sameLiquid(f2))
+       if (f1.sameLiquidRender(f2))
                return 0;
 
        u8 c1 = f1.solidness;
@@ -668,9 +653,9 @@ static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
        if (c1 == c2) {
                *equivalent = true;
                // If same solidness, liquid takes precense
-               if (f1.isLiquid())
+               if (f1.isLiquidRender())
                        return 1;
-               if (f2.isLiquid())
+               if (f2.isLiquidRender())
                        return 2;
        }
 
@@ -882,7 +867,7 @@ static void updateFastFaceRow(
 
        // Unroll this variable which has a significant build cost
        TileSpec next_tile;
-       for (u16 j = 0; j < MAP_BLOCKSIZE; j++) {
+       for (u16 j = 0; j < data->side_length; j++) {
                // If tiling can be done, this is set to false in the next step
                bool next_is_different = true;
 
@@ -893,7 +878,7 @@ 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) {
+               if (j != data->side_length - 1) {
                        p += translate_dir;
 
                        getTileInfo(data, p, face_dir,
@@ -956,8 +941,8 @@ static void updateAllFastFaceRows(MeshMakeData *data,
        /*
                Go through every y,z and get top(y+) faces in rows of x+
        */
-       for (s16 y = 0; y < MAP_BLOCKSIZE; y++)
-       for (s16 z = 0; z < MAP_BLOCKSIZE; z++)
+       for (s16 y = 0; y < data->side_length; y++)
+       for (s16 z = 0; z < data->side_length; z++)
                updateFastFaceRow(data,
                                v3s16(0, y, z),
                                v3s16(1, 0, 0), //dir
@@ -968,8 +953,8 @@ static void updateAllFastFaceRows(MeshMakeData *data,
        /*
                Go through every x,y and get right(x+) faces in rows of z+
        */
-       for (s16 x = 0; x < MAP_BLOCKSIZE; x++)
-       for (s16 y = 0; y < MAP_BLOCKSIZE; y++)
+       for (s16 x = 0; x < data->side_length; x++)
+       for (s16 y = 0; y < data->side_length; y++)
                updateFastFaceRow(data,
                                v3s16(x, y, 0),
                                v3s16(0, 0, 1), //dir
@@ -980,8 +965,8 @@ static void updateAllFastFaceRows(MeshMakeData *data,
        /*
                Go through every y,z and get back(z+) faces in rows of x+
        */
-       for (s16 z = 0; z < MAP_BLOCKSIZE; z++)
-       for (s16 y = 0; y < MAP_BLOCKSIZE; y++)
+       for (s16 z = 0; z < data->side_length; z++)
+       for (s16 y = 0; y < data->side_length; y++)
                updateFastFaceRow(data,
                                v3s16(0, y, z),
                                v3s16(1, 0, 0), //dir
@@ -1008,7 +993,7 @@ static void applyTileColor(PreMeshBuffer &pmb)
        MapBlockBspTree
 */
 
-void MapBlockBspTree::buildTree(const std::vector<MeshTriangle> *triangles)
+void MapBlockBspTree::buildTree(const std::vector<MeshTriangle> *triangles, u16 side_length)
 {
        this->triangles = triangles;
 
@@ -1021,14 +1006,19 @@ void MapBlockBspTree::buildTree(const std::vector<MeshTriangle> *triangles)
        for (u32 i = 0; i < triangles->size(); i++)
                indexes.push_back(i);
 
-       root = buildTree(v3f(1, 0, 0), v3f(85, 85, 85), 40, indexes, 0);
+       if (!indexes.empty()) {
+               // Start in the center of the block with increment of one quarter in each direction
+               root = buildTree(v3f(1, 0, 0), v3f((side_length + 1) * 0.5f * BS), side_length * 0.25f * BS, indexes, 0);
+       } else {
+               root = -1;
+       }
 }
 
 /**
  * @brief Find a candidate plane to split a set of triangles in two
- * 
+ *
  * The candidate plane is represented by one of the triangles from the set.
- * 
+ *
  * @param list Vector of indexes of the triangles in the set
  * @param triangles Vector of all triangles in the BSP tree
  * @return Address of the triangle that represents the proposed split plane
@@ -1097,7 +1087,7 @@ s32 MapBlockBspTree::buildTree(v3f normal, v3f origin, float delta, const std::v
                v3f next_normal = candidate_normal;
                v3f next_origin = origin + delta * normal;
                float next_delta = candidate_delta;
-               if (next_delta < 10) {
+               if (next_delta < 5) {
                        const MeshTriangle *candidate = findSplitCandidate(front_list, *triangles);
                        next_normal = candidate->getNormal();
                        next_origin = candidate->centroid;
@@ -1113,7 +1103,7 @@ s32 MapBlockBspTree::buildTree(v3f normal, v3f origin, float delta, const std::v
                v3f next_normal = candidate_normal;
                v3f next_origin = origin - delta * normal;
                float next_delta = candidate_delta;
-               if (next_delta < 10) {
+               if (next_delta < 5) {
                        const MeshTriangle *candidate = findSplitCandidate(back_list, *triangles);
                        next_normal = candidate->getNormal();
                        next_origin = candidate->centroid;
@@ -1169,7 +1159,7 @@ void PartialMeshBuffer::beforeDraw() const
 void PartialMeshBuffer::afterDraw() const
 {
        // Take the data back
-       m_vertex_indexes = std::move(m_buffer->Indices.steal());
+       m_vertex_indexes = m_buffer->Indices.steal();
 }
 
 /*
@@ -1177,7 +1167,6 @@ void PartialMeshBuffer::afterDraw() const
 */
 
 MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
-       m_minimap_mapblock(NULL),
        m_tsrc(data->m_client->getTextureSource()),
        m_shdrsrc(data->m_client->getShaderSource()),
        m_animation_force_timer(0), // force initial animation
@@ -1189,10 +1178,23 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        m_enable_shaders = data->m_use_shaders;
        m_enable_vbo = g_settings->getBool("enable_vbo");
 
-       if (data->m_client->getMinimap()) {
-               m_minimap_mapblock = new MinimapMapblock;
-               m_minimap_mapblock->getMinimapNodes(
-                       &data->m_vmanip, data->m_blockpos * MAP_BLOCKSIZE);
+       v3s16 bp = data->m_blockpos;
+       // Only generate minimap mapblocks at even coordinates.
+       if (data->m_mesh_grid.isMeshPos(bp) && data->m_client->getMinimap()) {
+               m_minimap_mapblocks.resize(data->m_mesh_grid.getCellVolume(), nullptr);
+               v3s16 ofs;
+
+               // See also client.cpp for the code that reads the array of minimap blocks.
+               for (ofs.Z = 0; ofs.Z < data->m_mesh_grid.cell_size; ofs.Z++)
+               for (ofs.Y = 0; ofs.Y < data->m_mesh_grid.cell_size; ofs.Y++)
+               for (ofs.X = 0; ofs.X < data->m_mesh_grid.cell_size; ofs.X++) {
+                       v3s16 p = (bp + ofs) * MAP_BLOCKSIZE;
+                       if (data->m_vmanip.getNodeNoEx(p).getContent() != CONTENT_IGNORE) {
+                               MinimapMapblock *block = new MinimapMapblock;
+                               m_minimap_mapblocks[data->m_mesh_grid.getOffsetIndex(ofs)] = block;
+                               block->getMinimapNodes(&data->m_vmanip, p);
+                       }
+               }
        }
 
        // 4-21ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
@@ -1220,7 +1222,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
                Convert FastFaces to MeshCollector
        */
 
-       MeshCollector collector;
+       v3f offset = intToFloat((data->m_blockpos - data->m_mesh_grid.getMeshPos(data->m_blockpos)) * MAP_BLOCKSIZE, BS);
+       MeshCollector collector(m_bounding_sphere_center, offset);
 
        {
                // avg 0ms (100ms spikes when loading textures the first time)
@@ -1256,6 +1259,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        const bool desync_animations = g_settings->getBool(
                "desynchronize_mapblock_texture_animation");
 
+       m_bounding_radius = std::sqrt(collector.m_bounding_radius_sq);
+
        for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
                for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
                {
@@ -1349,30 +1354,22 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
                        scene::SMeshBuffer *buf = new scene::SMeshBuffer();
                        buf->Material = material;
-                       switch (p.layer.material_type) {
-                       // list of transparent materials taken from tile.h
-                       case TILE_MATERIAL_ALPHA:
-                       case TILE_MATERIAL_LIQUID_TRANSPARENT:
-                       case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
-                               {
-                                       buf->append(&p.vertices[0], p.vertices.size(),
-                                               &p.indices[0], 0);
-
-                                       MeshTriangle t;
-                                       t.buffer = buf;
-                                       for (u32 i = 0; i < p.indices.size(); i += 3) {
-                                               t.p1 = p.indices[i];
-                                               t.p2 = p.indices[i + 1];
-                                               t.p3 = p.indices[i + 2];
-                                               t.updateAttributes();
-                                               m_transparent_triangles.push_back(t);
-                                       }
+                       if (p.layer.isTransparent()) {
+                               buf->append(&p.vertices[0], p.vertices.size(), nullptr, 0);
+
+                               MeshTriangle t;
+                               t.buffer = buf;
+                               m_transparent_triangles.reserve(p.indices.size() / 3);
+                               for (u32 i = 0; i < p.indices.size(); i += 3) {
+                                       t.p1 = p.indices[i];
+                                       t.p2 = p.indices[i + 1];
+                                       t.p3 = p.indices[i + 2];
+                                       t.updateAttributes();
+                                       m_transparent_triangles.push_back(t);
                                }
-                               break;
-                       default:
+                       } else {
                                buf->append(&p.vertices[0], p.vertices.size(),
                                        &p.indices[0], p.indices.size());
-                               break;
                        }
                        mesh->addMeshBuffer(buf);
                        buf->drop();
@@ -1386,7 +1383,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        }
 
        //std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
-       m_bsp_tree.buildTree(&m_transparent_triangles);
+       m_bsp_tree.buildTree(&m_transparent_triangles, data->side_length);
 
        // Check if animation is required for this mesh
        m_has_animation =
@@ -1398,17 +1395,10 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 MapBlockMesh::~MapBlockMesh()
 {
        for (scene::IMesh *m : m_mesh) {
-#if IRRLICHT_VERSION_MT_REVISION < 5
-               if (m_enable_vbo) {
-                       for (u32 i = 0; i < m->getMeshBufferCount(); i++) {
-                               scene::IMeshBuffer *buf = m->getMeshBuffer(i);
-                               RenderingEngine::get_video_driver()->removeHardwareBuffer(buf);
-                       }
-               }
-#endif
                m->drop();
        }
-       delete m_minimap_mapblock;
+       for (MinimapMapblock *block : m_minimap_mapblocks)
+               delete block;
 }
 
 bool MapBlockMesh::animate(bool faraway, float time, int crack,
@@ -1582,3 +1572,41 @@ video::SColor encode_light(u16 light, u8 emissive_light)
        float b = (day + night) / 2;
        return video::SColor(r, b, b, b);
 }
+
+std::unordered_map<v3s16, u8> get_solid_sides(MeshMakeData *data)
+{
+       std::unordered_map<v3s16, u8> results;
+       v3s16 ofs;
+       const u16 mesh_chunk = data->side_length / MAP_BLOCKSIZE;
+
+       for (ofs.X = 0; ofs.X < mesh_chunk; ofs.X++)
+       for (ofs.Y = 0; ofs.Y < mesh_chunk; ofs.Y++)
+       for (ofs.Z = 0; ofs.Z < mesh_chunk; ofs.Z++) {
+               v3s16 blockpos = data->m_blockpos + ofs;
+               v3s16 blockpos_nodes = blockpos * MAP_BLOCKSIZE;
+               const NodeDefManager *ndef = data->m_client->ndef();
+
+               u8 result = 0x3F; // all sides solid;
+
+               for (s16 i = 0; i < MAP_BLOCKSIZE && result != 0; i++)
+               for (s16 j = 0; j < MAP_BLOCKSIZE && result != 0; j++) {
+                       v3s16 positions[6] = {
+                               v3s16(0, i, j),
+                               v3s16(MAP_BLOCKSIZE - 1, i, j),
+                               v3s16(i, 0, j),
+                               v3s16(i, MAP_BLOCKSIZE - 1, j),
+                               v3s16(i, j, 0),
+                               v3s16(i, j, MAP_BLOCKSIZE - 1)
+                       };
+
+                       for (u8 k = 0; k < 6; k++) {
+                               const MapNode &top = data->m_vmanip.getNodeRefUnsafe(blockpos_nodes + positions[k]);
+                               if (ndef->get(top).solidness != 2)
+                                       result &= ~(1 << k);
+                       }
+               }
+
+               results[blockpos] = result;
+       }
+       return results;
+}