LocalPlayer::accelerateHorizontal: cleanups
[oweals/minetest.git] / src / content_mapblock.cpp
index e6dd8e83e7dddbfc1cc4954c7cad009a2d43ca8e..935240dae72e119b967d7b757b415ce6b4cb5f0a 100644 (file)
@@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "client/tile.h"
 #include "mesh.h"
 #include <IMeshManipulator.h>
+#include "client/renderingengine.h"
 #include "client.h"
 #include "log.h"
 #include "noise.h"
-#include "util/cpp11.h"
 
 // Distance of light extrapolation (for oversized nodes)
 // After this distance, it gives up and considers light level constant
@@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 // Corresponding offsets are listed in g_27dirs
 #define FRAMED_NEIGHBOR_COUNT 18
 
-static constexpr v3s16 light_dirs[8] = {
+static const v3s16 light_dirs[8] = {
        v3s16(-1, -1, -1),
        v3s16(-1, -1,  1),
        v3s16(-1,  1, -1),
@@ -65,8 +65,7 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector
        collector = output;
 
        nodedef   = data->m_client->ndef();
-       smgr      = data->m_client->getSceneManager();
-       meshmanip = smgr->getMeshManipulator();
+       meshmanip = RenderingEngine::get_scene_manager()->getMeshManipulator();
 
        enable_mesh_cache = g_settings->getBool("enable_mesh_cache") &&
                !data->m_smooth_lighting; // Mesh cache is not supported with smooth lighting
@@ -74,33 +73,49 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector
        blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
 }
 
-void MapblockMeshGenerator::useTile(int index, bool disable_backface_culling)
+void MapblockMeshGenerator::useTile(int index, u8 set_flags, u8 reset_flags, bool special)
 {
-       getNodeTileN(n, p, index, data, tile);
+       if (special)
+               getSpecialTile(index, &tile, p == data->m_crack_pos_relative);
+       else
+               getNodeTileN(n, p, index, data, tile);
        if (!data->m_smooth_lighting)
                color = encode_light(light, f->light_source);
        for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
-               tile.layers[layer].material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
-               if (disable_backface_culling)
-                       tile.layers[layer].material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
+               tile.layers[layer].material_flags |= set_flags;
+               tile.layers[layer].material_flags &= ~reset_flags;
        }
 }
 
-void MapblockMeshGenerator::useDefaultTile(bool set_color)
+void MapblockMeshGenerator::getTile(v3s16 direction, TileSpec *tile)
 {
-       getNodeTile(n, p, v3s16(0, 0, 0), data, tile);
-       if (set_color && !data->m_smooth_lighting)
-               color = encode_light(light, f->light_source);
+       getNodeTile(n, p, direction, data, *tile);
 }
 
-void MapblockMeshGenerator::getTile(const v3s16& direction, TileSpec &tile)
+/*!
+ * Returns the i-th special tile for a map node.
+ */
+void MapblockMeshGenerator::getSpecialTile(int index, TileSpec *tile, bool apply_crack)
 {
-       getNodeTile(n, p, direction, data, tile);
+       *tile = f->special_tiles[index];
+       TileLayer *top_layer = NULL;
+       for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
+               TileLayer *layer = &tile->layers[layernum];
+               if (layer->texture_id == 0)
+                       continue;
+               top_layer = layer;
+               if (!layer->has_color)
+                       n.getColor(*f, &layer->color);
+       }
+       if (apply_crack)
+               top_layer->material_flags |= MATERIAL_FLAG_CRACK;
 }
 
-void MapblockMeshGenerator::drawQuad(v3f *coords, const v3s16 &normal)
+void MapblockMeshGenerator::drawQuad(v3f *coords, const v3s16 &normal,
+       float vertical_tiling)
 {
-       static const v2f tcoords[4] = {v2f(0, 0), v2f(1, 0), v2f(1, 1), v2f(0, 1)};
+       const v2f tcoords[4] = {v2f(0.0, 0.0), v2f(1.0, 0.0),
+               v2f(1.0, vertical_tiling), v2f(0.0, vertical_tiling)};
        video::S3DVertex vertices[4];
        bool shade_face = !f->light_source && (normal != v3s16(0, 0, 0));
        v3f normal2(normal.X, normal.Y, normal.Z);
@@ -359,27 +374,10 @@ void MapblockMeshGenerator::drawAutoLightedCuboid(aabb3f box, const f32 *txc,
        }
 }
 
-/*!
- * Returns the i-th special tile for a map node.
- */
-static TileSpec getSpecialTile(const ContentFeatures &f,
-       const MapNode &n, u8 i)
-{
-       TileSpec copy = f.special_tiles[i];
-       for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
-               TileLayer *layer = &copy.layers[layernum];
-               if (layer->texture_id == 0)
-                       continue;
-               if (!layer->has_color)
-                       n.getColor(f, &(layer->color));
-       }
-       return copy;
-}
-
 void MapblockMeshGenerator::prepareLiquidNodeDrawing()
 {
-       tile_liquid_top = getSpecialTile(*f, n, 0);
-       tile_liquid = getSpecialTile(*f, n, 1);
+       getSpecialTile(0, &tile_liquid_top);
+       getSpecialTile(1, &tile_liquid);
 
        MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(p.X, p.Y + 1, p.Z));
        c_flowing = nodedef->getId(f->liquid_alternative_flowing);
@@ -604,7 +602,7 @@ void MapblockMeshGenerator::drawLiquidNode()
 
 void MapblockMeshGenerator::drawGlasslikeNode()
 {
-       useDefaultTile();
+       useTile(0, 0, 0);
 
        for (int face = 0; face < 6; face++) {
                // Check this neighbor
@@ -639,7 +637,7 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode()
 {
        TileSpec tiles[6];
        for (int face = 0; face < 6; face++)
-               getTile(g_6dirs[face], tiles[face]);
+               getTile(g_6dirs[face], &tiles[face]);
 
        TileSpec glass_tiles[6];
        if (tiles[1].layers[0].texture &&
@@ -752,7 +750,7 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode()
                // Internal liquid level has param2 range 0 .. 63,
                // convert it to -0.5 .. 0.5
                float vlev = (param2 / 63.0) * 2.0 - 1.0;
-               tile = getSpecialTile(*f, n, 0);
+               getSpecialTile(0, &tile);
                drawAutoLightedCuboid(aabb3f(-(nb[5] ? g : b),
                                             -(nb[4] ? g : b),
                                             -(nb[3] ? g : b),
@@ -765,7 +763,7 @@ void MapblockMeshGenerator::drawGlasslikeFramedNode()
 void MapblockMeshGenerator::drawAllfacesNode()
 {
        static const aabb3f box(-BS / 2, -BS / 2, -BS / 2, BS / 2, BS / 2, BS / 2);
-       useDefaultTile(false);
+       useTile(0, 0, 0);
        drawAutoLightedCuboid(box);
 }
 
@@ -778,7 +776,7 @@ void MapblockMeshGenerator::drawTorchlikeNode()
                case DWM_YN: tileindex = 0; break; // floor
                default:     tileindex = 2; // side (or invalid—should we care?)
        }
-       useTile(tileindex, true);
+       useTile(tileindex, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING);
 
        float size = BS / 2 * f->visual_scale;
        v3f vertices[4] = {
@@ -803,7 +801,7 @@ void MapblockMeshGenerator::drawTorchlikeNode()
 void MapblockMeshGenerator::drawSignlikeNode()
 {
        u8 wall = n.getWallMounted(nodedef);
-       useTile(0, true);
+       useTile(0, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING);
        static const float offset = BS / 16;
        float size = BS / 2 * f->visual_scale;
        // Wall at X+ of node
@@ -830,14 +828,14 @@ void MapblockMeshGenerator::drawPlantlikeQuad(float rotation, float quad_offset,
        bool offset_top_only)
 {
        v3f vertices[4] = {
-               v3f(-scale, -BS / 2 + scale * 2, 0),
-               v3f( scale, -BS / 2 + scale * 2, 0),
+               v3f(-scale, -BS / 2 + 2.0 * scale * plant_height, 0),
+               v3f( scale, -BS / 2 + 2.0 * scale * plant_height, 0),
                v3f( scale, -BS / 2, 0),
                v3f(-scale, -BS / 2, 0),
        };
        if (random_offset_Y) {
                PseudoRandom yrng(face_num++ | p.X << 16 | p.Z << 8 | p.Y << 24);
-               offset.Y = BS * ((yrng.next() % 16 / 16.0) * 0.125);
+               offset.Y = -BS * ((yrng.next() % 16 / 16.0) * 0.125);
        }
        int offset_count = offset_top_only ? 2 : 4;
        for (int i = 0; i < offset_count; i++)
@@ -846,18 +844,18 @@ void MapblockMeshGenerator::drawPlantlikeQuad(float rotation, float quad_offset,
                vertices[i].rotateXZBy(rotation + rotate_degree);
                vertices[i] += offset;
        }
-       drawQuad(vertices);
+       drawQuad(vertices, v3s16(0, 0, 0), plant_height);
 }
 
-void MapblockMeshGenerator::drawPlantlikeNode()
+void MapblockMeshGenerator::drawPlantlike()
 {
-       useTile(0, false);
        draw_style = PLANT_STYLE_CROSS;
        scale = BS / 2 * f->visual_scale;
        offset = v3f(0, 0, 0);
        rotate_degree = 0;
        random_offset_Y = false;
        face_num = 0;
+       plant_height = 1.0;
 
        switch (f->param_type_2) {
        case CPT2_MESHOPTIONS:
@@ -877,6 +875,10 @@ void MapblockMeshGenerator::drawPlantlikeNode()
                rotate_degree = n.param2 * 2;
                break;
 
+       case CPT2_LEVELED:
+               plant_height = n.param2 / 16.0;
+               break;
+
        default:
                break;
        }
@@ -914,6 +916,27 @@ void MapblockMeshGenerator::drawPlantlikeNode()
        }
 }
 
+void MapblockMeshGenerator::drawPlantlikeNode()
+{
+       useTile();
+       drawPlantlike();
+}
+
+void MapblockMeshGenerator::drawPlantlikeRootedNode()
+{
+       useTile(0, MATERIAL_FLAG_CRACK_OVERLAY, 0, true);
+       origin += v3f(0.0, BS, 0.0);
+       p.Y++;
+       if (data->m_smooth_lighting) {
+               getSmoothLightFrame();
+       } else {
+               MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
+               light = getInteriorLight(ntop, 1, nodedef);
+       }
+       drawPlantlike();
+       p.Y--;
+}
+
 void MapblockMeshGenerator::drawFirelikeQuad(float rotation, float opening_angle,
        float offset_h, float offset_v)
 {
@@ -934,7 +957,7 @@ void MapblockMeshGenerator::drawFirelikeQuad(float rotation, float opening_angle
 
 void MapblockMeshGenerator::drawFirelikeNode()
 {
-       useTile(0, false);
+       useTile();
        scale = BS / 2 * f->visual_scale;
 
        // Check for adjacent nodes
@@ -981,7 +1004,7 @@ void MapblockMeshGenerator::drawFirelikeNode()
 
 void MapblockMeshGenerator::drawFencelikeNode()
 {
-       useDefaultTile(false);
+       useTile(0, 0, 0);
        TileSpec tile_nocrack = tile;
        for (int layer = 0; layer < MAX_TILE_LAYERS; layer++)
                tile_nocrack.layers[layer].material_flags &= ~MATERIAL_FLAG_CRACK;
@@ -1131,7 +1154,7 @@ void MapblockMeshGenerator::drawRaillikeNode()
                angle = rail_kinds[code].angle;
        }
 
-       useTile(tile_index, true);
+       useTile(tile_index, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING);
 
        static const float offset = BS / 64;
        static const float size   = BS / 2;
@@ -1172,7 +1195,7 @@ void MapblockMeshGenerator::drawNodeboxNode()
        TileSpec tiles[6];
        for (int face = 0; face < 6; face++) {
                // Handles facedir rotation for textures
-               getTile(tile_dirs[face], tiles[face]);
+               getTile(tile_dirs[face], &tiles[face]);
        }
 
        // locate possible neighboring nodes to connect to
@@ -1229,7 +1252,7 @@ void MapblockMeshGenerator::drawMeshNode()
 
        int mesh_buffer_count = mesh->getMeshBufferCount();
        for (int j = 0; j < mesh_buffer_count; j++) {
-               useTile(j, false);
+               useTile(j);
                scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
                video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
                int vertex_count = buf->getVertexCount();
@@ -1265,6 +1288,16 @@ void MapblockMeshGenerator::errorUnknownDrawtype()
 
 void MapblockMeshGenerator::drawNode()
 {
+       // skip some drawtypes early
+       switch (f->drawtype) {
+               case NDT_NORMAL:   // Drawn by MapBlockMesh
+               case NDT_AIRLIKE:  // Not drawn at all
+               case NDT_LIQUID:   // Drawn by MapBlockMesh
+                       return;
+               default:
+                       break;
+       }
+       origin = intToFloat(p, BS);
        if (data->m_smooth_lighting)
                getSmoothLightFrame();
        else
@@ -1277,6 +1310,7 @@ void MapblockMeshGenerator::drawNode()
                case NDT_TORCHLIKE:         drawTorchlikeNode(); break;
                case NDT_SIGNLIKE:          drawSignlikeNode(); break;
                case NDT_PLANTLIKE:         drawPlantlikeNode(); break;
+               case NDT_PLANTLIKE_ROOTED:  drawPlantlikeRootedNode(); break;
                case NDT_FIRELIKE:          drawFirelikeNode(); break;
                case NDT_FENCELIKE:         drawFencelikeNode(); break;
                case NDT_RAILLIKE:          drawRaillikeNode(); break;
@@ -1297,12 +1331,6 @@ void MapblockMeshGenerator::generate()
        for (p.X = 0; p.X < MAP_BLOCKSIZE; p.X++) {
                n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
                f = &nodedef->get(n);
-               // Solid nodes are drawn by MapBlockMesh
-               if (f->solidness != 0)
-                       continue;
-               if (f->drawtype == NDT_AIRLIKE)
-                       continue;
-               origin = intToFloat(p, BS);
                drawNode();
        }
 }