LCOV - code coverage report
Current view: top level - src - mapblock_mesh.cpp (source / functions) Hit Total Coverage
Test: report Lines: 606 726 83.5 %
Date: 2015-07-11 18:23:49 Functions: 33 34 97.1 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #include "mapblock_mesh.h"
      21             : #include "light.h"
      22             : #include "mapblock.h"
      23             : #include "map.h"
      24             : #include "profiler.h"
      25             : #include "nodedef.h"
      26             : #include "gamedef.h"
      27             : #include "mesh.h"
      28             : #include "minimap.h"
      29             : #include "content_mapblock.h"
      30             : #include "noise.h"
      31             : #include "shader.h"
      32             : #include "settings.h"
      33             : #include "util/directiontables.h"
      34             : #include <IMeshManipulator.h>
      35             : 
      36     4987909 : static void applyFacesShading(video::SColor& color, float factor)
      37             : {
      38     4987909 :         color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
      39     4987909 :         color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
      40     4987909 : }
      41             : 
      42             : /*
      43             :         MeshMakeData
      44             : */
      45             : 
      46        3549 : MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders):
      47             :         m_vmanip(),
      48             :         m_blockpos(-1337,-1337,-1337),
      49             :         m_crack_pos_relative(-1337, -1337, -1337),
      50             :         m_highlighted_pos_relative(-1337, -1337, -1337),
      51             :         m_smooth_lighting(false),
      52             :         m_show_hud(false),
      53             :         m_highlight_mesh_color(255, 255, 255, 255),
      54             :         m_gamedef(gamedef),
      55        3549 :         m_use_shaders(use_shaders)
      56        3549 : {}
      57             : 
      58        3548 : void MeshMakeData::fill(MapBlock *block)
      59             : {
      60        3548 :         m_blockpos = block->getPos();
      61             : 
      62        3548 :         v3s16 blockpos_nodes = m_blockpos*MAP_BLOCKSIZE;
      63             : 
      64             :         /*
      65             :                 Copy data
      66             :         */
      67             : 
      68             :         // Allocate this block + neighbors
      69        3548 :         m_vmanip.clear();
      70        7096 :         VoxelArea voxel_area(blockpos_nodes - v3s16(1,1,1) * MAP_BLOCKSIZE,
      71       10644 :                         blockpos_nodes + v3s16(1,1,1) * MAP_BLOCKSIZE*2-v3s16(1,1,1));
      72        3548 :         m_vmanip.addArea(voxel_area);
      73             : 
      74             :         {
      75             :                 //TimeTaker timer("copy central block data");
      76             :                 // 0ms
      77             : 
      78             :                 // Copy our data
      79        3548 :                 block->copyTo(m_vmanip);
      80             :         }
      81             :         {
      82             :                 //TimeTaker timer("copy neighbor block data");
      83             :                 // 0ms
      84             : 
      85             :                 /*
      86             :                         Copy neighbors. This is lightning fast.
      87             :                         Copying only the borders would be *very* slow.
      88             :                 */
      89             : 
      90             :                 // Get map
      91        3548 :                 Map *map = block->getParent();
      92             : 
      93       95796 :                 for(u16 i=0; i<26; i++)
      94             :                 {
      95       92248 :                         const v3s16 &dir = g_26dirs[i];
      96       92248 :                         v3s16 bp = m_blockpos + dir;
      97       92248 :                         MapBlock *b = map->getBlockNoCreateNoEx(bp);
      98       92248 :                         if(b)
      99       52772 :                                 b->copyTo(m_vmanip);
     100             :                 }
     101             :         }
     102        3548 : }
     103             : 
     104           1 : void MeshMakeData::fillSingleNode(MapNode *node)
     105             : {
     106           1 :         m_blockpos = v3s16(0,0,0);
     107             : 
     108           1 :         v3s16 blockpos_nodes = v3s16(0,0,0);
     109           2 :         VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE,
     110           3 :                         blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1));
     111           1 :         s32 volume = area.getVolume();
     112           1 :         s32 our_node_index = area.index(1,1,1);
     113             : 
     114             :         // Allocate this block + neighbors
     115           1 :         m_vmanip.clear();
     116           1 :         m_vmanip.addArea(area);
     117             : 
     118             :         // Fill in data
     119           1 :         MapNode *data = new MapNode[volume];
     120      110593 :         for(s32 i = 0; i < volume; i++)
     121             :         {
     122      110592 :                 if(i == our_node_index)
     123             :                 {
     124           1 :                         data[i] = *node;
     125             :                 }
     126             :                 else
     127             :                 {
     128      110591 :                         data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0);
     129             :                 }
     130             :         }
     131           1 :         m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent());
     132           1 :         delete[] data;
     133           1 : }
     134             : 
     135        3548 : void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
     136             : {
     137        3548 :         if(crack_level >= 0)
     138           0 :                 m_crack_pos_relative = crack_pos - m_blockpos*MAP_BLOCKSIZE;
     139        3548 : }
     140             : 
     141        3548 : void MeshMakeData::setHighlighted(v3s16 highlighted_pos, bool show_hud)
     142             : {
     143        3548 :         m_show_hud = show_hud;
     144        3548 :         m_highlighted_pos_relative = highlighted_pos - m_blockpos*MAP_BLOCKSIZE;
     145        3548 : }
     146             : 
     147        3548 : void MeshMakeData::setSmoothLighting(bool smooth_lighting)
     148             : {
     149        3548 :         m_smooth_lighting = smooth_lighting;
     150        3548 : }
     151             : 
     152             : /*
     153             :         Light and vertex color functions
     154             : */
     155             : 
     156             : /*
     157             :         Calculate non-smooth lighting at interior of node.
     158             :         Single light bank.
     159             : */
     160      329420 : static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
     161             :                 INodeDefManager *ndef)
     162             : {
     163      329420 :         u8 light = n.getLight(bank, ndef);
     164             : 
     165      852176 :         while(increment > 0)
     166             :         {
     167      261378 :                 light = undiminish_light(light);
     168      261378 :                 --increment;
     169             :         }
     170      334460 :         while(increment < 0)
     171             :         {
     172        2520 :                 light = diminish_light(light);
     173        2520 :                 ++increment;
     174             :         }
     175             : 
     176      329420 :         return decode_light(light);
     177             : }
     178             : 
     179             : /*
     180             :         Calculate non-smooth lighting at interior of node.
     181             :         Both light banks.
     182             : */
     183      164710 : u16 getInteriorLight(MapNode n, s32 increment, INodeDefManager *ndef)
     184             : {
     185      164710 :         u16 day = getInteriorLight(LIGHTBANK_DAY, n, increment, ndef);
     186      164710 :         u16 night = getInteriorLight(LIGHTBANK_NIGHT, n, increment, ndef);
     187      164710 :         return day | (night << 8);
     188             : }
     189             : 
     190             : /*
     191             :         Calculate non-smooth lighting at face of node.
     192             :         Single light bank.
     193             : */
     194          12 : static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
     195             :                 v3s16 face_dir, INodeDefManager *ndef)
     196             : {
     197             :         u8 light;
     198          12 :         u8 l1 = n.getLight(bank, ndef);
     199          12 :         u8 l2 = n2.getLight(bank, ndef);
     200          12 :         if(l1 > l2)
     201           3 :                 light = l1;
     202             :         else
     203           9 :                 light = l2;
     204             : 
     205             :         // Boost light level for light sources
     206          12 :         u8 light_source = MYMAX(ndef->get(n).light_source,
     207             :                         ndef->get(n2).light_source);
     208          12 :         if(light_source > light)
     209           0 :                 light = light_source;
     210             : 
     211          12 :         return decode_light(light);
     212             : }
     213             : 
     214             : /*
     215             :         Calculate non-smooth lighting at face of node.
     216             :         Both light banks.
     217             : */
     218           6 : u16 getFaceLight(MapNode n, MapNode n2, v3s16 face_dir, INodeDefManager *ndef)
     219             : {
     220           6 :         u16 day = getFaceLight(LIGHTBANK_DAY, n, n2, face_dir, ndef);
     221           6 :         u16 night = getFaceLight(LIGHTBANK_NIGHT, n, n2, face_dir, ndef);
     222           6 :         return day | (night << 8);
     223             : }
     224             : 
     225             : /*
     226             :         Calculate smooth lighting at the XYZ- corner of p.
     227             :         Both light banks
     228             : */
     229     3433720 : static u16 getSmoothLightCombined(v3s16 p, MeshMakeData *data)
     230             : {
     231             :         static const v3s16 dirs8[8] = {
     232             :                 v3s16(0,0,0),
     233             :                 v3s16(0,0,1),
     234             :                 v3s16(0,1,0),
     235             :                 v3s16(0,1,1),
     236             :                 v3s16(1,0,0),
     237             :                 v3s16(1,1,0),
     238             :                 v3s16(1,0,1),
     239             :                 v3s16(1,1,1),
     240     3433720 :         };
     241             : 
     242     3433720 :         INodeDefManager *ndef = data->m_gamedef->ndef();
     243             : 
     244     3433720 :         u16 ambient_occlusion = 0;
     245     3433720 :         u16 light_count = 0;
     246     3433720 :         u8 light_source_max = 0;
     247     3433720 :         u16 light_day = 0;
     248     3433720 :         u16 light_night = 0;
     249             : 
     250    30903480 :         for (u32 i = 0; i < 8; i++)
     251             :         {
     252    27469760 :                 const MapNode &n = data->m_vmanip.getNodeRefUnsafeCheckFlags(p - dirs8[i]);
     253             : 
     254             :                 // if it's CONTENT_IGNORE we can't do any light calculations
     255    27469760 :                 if (n.getContent() == CONTENT_IGNORE) {
     256      386199 :                         continue;
     257             :                 }
     258             : 
     259    27083561 :                 const ContentFeatures &f = ndef->get(n);
     260    27083561 :                 if (f.light_source > light_source_max)
     261      175886 :                         light_source_max = f.light_source;
     262             :                 // Check f.solidness because fast-style leaves look better this way
     263    27083561 :                 if (f.param_type == CPT_LIGHT && f.solidness != 2) {
     264    13889392 :                         light_day += decode_light(n.getLightNoChecks(LIGHTBANK_DAY, &f));
     265    13889392 :                         light_night += decode_light(n.getLightNoChecks(LIGHTBANK_NIGHT, &f));
     266    13889392 :                         light_count++;
     267             :                 } else {
     268    13194169 :                         ambient_occlusion++;
     269             :                 }
     270             :         }
     271             : 
     272     3433720 :         if(light_count == 0)
     273           0 :                 return 0xffff;
     274             : 
     275     3433720 :         light_day /= light_count;
     276     3433720 :         light_night /= light_count;
     277             : 
     278             :         // Boost brightness around light sources
     279     3433720 :         bool skip_ambient_occlusion_day = false;
     280     3433720 :         if(decode_light(light_source_max) >= light_day) {
     281      777356 :                 light_day = decode_light(light_source_max);
     282      777356 :                 skip_ambient_occlusion_day = true;
     283             :         }
     284             : 
     285     3433720 :         bool skip_ambient_occlusion_night = false;
     286     3433720 :         if(decode_light(light_source_max) >= light_night) {
     287     2155926 :                 light_night = decode_light(light_source_max);
     288     2155926 :                 skip_ambient_occlusion_night = true;
     289             :         }
     290             : 
     291     3433720 :         if (ambient_occlusion > 4)
     292             :         {
     293     1255862 :                 static const float ao_gamma = rangelim(
     294             :                         g_settings->getFloat("ambient_occlusion_gamma"), 0.25, 4.0);
     295             : 
     296             :                 // Table of gamma space multiply factors.
     297             :                 static const float light_amount[3] = {
     298           1 :                         powf(0.75, 1.0 / ao_gamma),
     299           1 :                         powf(0.5,  1.0 / ao_gamma),
     300           1 :                         powf(0.25, 1.0 / ao_gamma)
     301     1255865 :                 };
     302             : 
     303             :                 //calculate table index for gamma space multiplier
     304     1255862 :                 ambient_occlusion -= 5;
     305             : 
     306     1255862 :                 if (!skip_ambient_occlusion_day)
     307      850354 :                         light_day = rangelim(core::round32(light_day*light_amount[ambient_occlusion]), 0, 255);
     308     1255862 :                 if (!skip_ambient_occlusion_night)
     309      449699 :                         light_night = rangelim(core::round32(light_night*light_amount[ambient_occlusion]), 0, 255);
     310             :         }
     311             : 
     312     3433720 :         return light_day | (light_night << 8);
     313             : }
     314             : 
     315             : /*
     316             :         Calculate smooth lighting at the given corner of p.
     317             :         Both light banks.
     318             : */
     319     3433720 : u16 getSmoothLight(v3s16 p, v3s16 corner, MeshMakeData *data)
     320             : {
     321     3433720 :         if(corner.X == 1) p.X += 1;
     322             :         // else corner.X == -1
     323     3433720 :         if(corner.Y == 1) p.Y += 1;
     324             :         // else corner.Y == -1
     325     3433720 :         if(corner.Z == 1) p.Z += 1;
     326             :         // else corner.Z == -1
     327             : 
     328     3433720 :         return getSmoothLightCombined(p, data);
     329             : }
     330             : 
     331             : /*
     332             :         Converts from day + night color values (0..255)
     333             :         and a given daynight_ratio to the final SColor shown on screen.
     334             : */
     335       74322 : void finalColorBlend(video::SColor& result,
     336             :                 u8 day, u8 night, u32 daynight_ratio)
     337             : {
     338       74322 :         s32 rg = (day * daynight_ratio + night * (1000-daynight_ratio)) / 1000;
     339       74322 :         s32 b = rg;
     340             : 
     341             :         // Moonlight is blue
     342       74322 :         b += (day - night) / 13;
     343       74322 :         rg -= (day - night) / 23;
     344             : 
     345             :         // Emphase blue a bit in darker places
     346             :         // Each entry of this array represents a range of 8 blue levels
     347             :         static const u8 emphase_blue_when_dark[32] = {
     348             :                 1, 4, 6, 6, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0,
     349             :                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     350             :         };
     351       74322 :         b += emphase_blue_when_dark[irr::core::clamp(b, 0, 255) / 8];
     352       74322 :         b = irr::core::clamp(b, 0, 255);
     353             : 
     354             :         // Artificial light is yellow-ish
     355             :         static const u8 emphase_yellow_when_artificial[16] = {
     356             :                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 15, 15, 15
     357             :         };
     358       74322 :         rg += emphase_yellow_when_artificial[night/16];
     359       74322 :         rg = irr::core::clamp(rg, 0, 255);
     360             : 
     361       74322 :         result.setRed(rg);
     362       74322 :         result.setGreen(rg);
     363       74322 :         result.setBlue(b);
     364       74322 : }
     365             : 
     366             : /*
     367             :         Mesh generation helpers
     368             : */
     369             : 
     370             : /*
     371             :         vertex_dirs: v3s16[4]
     372             : */
     373     1632651 : static void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs)
     374             : {
     375             :         /*
     376             :                 If looked from outside the node towards the face, the corners are:
     377             :                 0: bottom-right
     378             :                 1: bottom-left
     379             :                 2: top-left
     380             :                 3: top-right
     381             :         */
     382     1632651 :         if(dir == v3s16(0,0,1))
     383             :         {
     384             :                 // If looking towards z+, this is the face that is behind
     385             :                 // the center point, facing towards z+.
     386      214664 :                 vertex_dirs[0] = v3s16(-1,-1, 1);
     387      214664 :                 vertex_dirs[1] = v3s16( 1,-1, 1);
     388      214664 :                 vertex_dirs[2] = v3s16( 1, 1, 1);
     389      214664 :                 vertex_dirs[3] = v3s16(-1, 1, 1);
     390             :         }
     391     1417987 :         else if(dir == v3s16(0,0,-1))
     392             :         {
     393             :                 // faces towards Z-
     394      214601 :                 vertex_dirs[0] = v3s16( 1,-1,-1);
     395      214601 :                 vertex_dirs[1] = v3s16(-1,-1,-1);
     396      214601 :                 vertex_dirs[2] = v3s16(-1, 1,-1);
     397      214601 :                 vertex_dirs[3] = v3s16( 1, 1,-1);
     398             :         }
     399     1203386 :         else if(dir == v3s16(1,0,0))
     400             :         {
     401             :                 // faces towards X+
     402      228702 :                 vertex_dirs[0] = v3s16( 1,-1, 1);
     403      228702 :                 vertex_dirs[1] = v3s16( 1,-1,-1);
     404      228702 :                 vertex_dirs[2] = v3s16( 1, 1,-1);
     405      228702 :                 vertex_dirs[3] = v3s16( 1, 1, 1);
     406             :         }
     407      974684 :         else if(dir == v3s16(-1,0,0))
     408             :         {
     409             :                 // faces towards X-
     410      227500 :                 vertex_dirs[0] = v3s16(-1,-1,-1);
     411      227500 :                 vertex_dirs[1] = v3s16(-1,-1, 1);
     412      227500 :                 vertex_dirs[2] = v3s16(-1, 1, 1);
     413      227500 :                 vertex_dirs[3] = v3s16(-1, 1,-1);
     414             :         }
     415      747184 :         else if(dir == v3s16(0,1,0))
     416             :         {
     417             :                 // faces towards Y+ (assume Z- as "down" in texture)
     418      580883 :                 vertex_dirs[0] = v3s16( 1, 1,-1);
     419      580883 :                 vertex_dirs[1] = v3s16(-1, 1,-1);
     420      580883 :                 vertex_dirs[2] = v3s16(-1, 1, 1);
     421      580883 :                 vertex_dirs[3] = v3s16( 1, 1, 1);
     422             :         }
     423      166301 :         else if(dir == v3s16(0,-1,0))
     424             :         {
     425             :                 // faces towards Y- (assume Z+ as "down" in texture)
     426      166301 :                 vertex_dirs[0] = v3s16( 1,-1, 1);
     427      166301 :                 vertex_dirs[1] = v3s16(-1,-1, 1);
     428      166301 :                 vertex_dirs[2] = v3s16(-1,-1,-1);
     429      166301 :                 vertex_dirs[3] = v3s16( 1,-1,-1);
     430             :         }
     431     1632651 : }
     432             : 
     433     3940660 : struct FastFace
     434             : {
     435             :         TileSpec tile;
     436             :         video::S3DVertex vertices[4]; // Precalculated vertices
     437             : };
     438             : 
     439      774221 : static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
     440             :                 v3f p, v3s16 dir, v3f scale, u8 light_source, std::vector<FastFace> &dest)
     441             : {
     442             :         // Position is at the center of the cube.
     443      774221 :         v3f pos = p * BS;
     444             : 
     445      774221 :         float x0 = 0.0;
     446      774221 :         float y0 = 0.0;
     447      774221 :         float w = 1.0;
     448      774221 :         float h = 1.0;
     449             : 
     450      774221 :         v3f vertex_pos[4];
     451      774221 :         v3s16 vertex_dirs[4];
     452      774221 :         getNodeVertexDirs(dir, vertex_dirs);
     453             : 
     454      774221 :         v3s16 t;
     455             :         u16 t1;
     456      774221 :         switch (tile.rotation)
     457             :         {
     458             :         case 0:
     459      770216 :                 break;
     460             :         case 1: //R90
     461        1849 :                 t = vertex_dirs[0];
     462        1849 :                 vertex_dirs[0] = vertex_dirs[3];
     463        1849 :                 vertex_dirs[3] = vertex_dirs[2];
     464        1849 :                 vertex_dirs[2] = vertex_dirs[1];
     465        1849 :                 vertex_dirs[1] = t;
     466        1849 :                 t1=li0;
     467        1849 :                 li0=li3;
     468        1849 :                 li3=li2;
     469        1849 :                 li2=li1;
     470        1849 :                 li1=t1;
     471        1849 :                 break;
     472             :         case 2: //R180
     473         901 :                 t = vertex_dirs[0];
     474         901 :                 vertex_dirs[0] = vertex_dirs[2];
     475         901 :                 vertex_dirs[2] = t;
     476         901 :                 t = vertex_dirs[1];
     477         901 :                 vertex_dirs[1] = vertex_dirs[3];
     478         901 :                 vertex_dirs[3] = t;
     479         901 :                 t1  = li0;
     480         901 :                 li0 = li2;
     481         901 :                 li2 = t1;
     482         901 :                 t1  = li1;
     483         901 :                 li1 = li3;
     484         901 :                 li3 = t1;
     485         901 :                 break;
     486             :         case 3: //R270
     487        1255 :                 t = vertex_dirs[0];
     488        1255 :                 vertex_dirs[0] = vertex_dirs[1];
     489        1255 :                 vertex_dirs[1] = vertex_dirs[2];
     490        1255 :                 vertex_dirs[2] = vertex_dirs[3];
     491        1255 :                 vertex_dirs[3] = t;
     492        1255 :                 t1  = li0;
     493        1255 :                 li0 = li1;
     494        1255 :                 li1 = li2;
     495        1255 :                 li2 = li3;
     496        1255 :                 li3 = t1;
     497        1255 :                 break;
     498             :         case 4: //FXR90
     499           0 :                 t = vertex_dirs[0];
     500           0 :                 vertex_dirs[0] = vertex_dirs[3];
     501           0 :                 vertex_dirs[3] = vertex_dirs[2];
     502           0 :                 vertex_dirs[2] = vertex_dirs[1];
     503           0 :                 vertex_dirs[1] = t;
     504           0 :                 t1  = li0;
     505           0 :                 li0 = li3;
     506           0 :                 li3 = li2;
     507           0 :                 li2 = li1;
     508           0 :                 li1 = t1;
     509           0 :                 y0 += h;
     510           0 :                 h *= -1;
     511           0 :                 break;
     512             :         case 5: //FXR270
     513           0 :                 t = vertex_dirs[0];
     514           0 :                 vertex_dirs[0] = vertex_dirs[1];
     515           0 :                 vertex_dirs[1] = vertex_dirs[2];
     516           0 :                 vertex_dirs[2] = vertex_dirs[3];
     517           0 :                 vertex_dirs[3] = t;
     518           0 :                 t1  = li0;
     519           0 :                 li0 = li1;
     520           0 :                 li1 = li2;
     521           0 :                 li2 = li3;
     522           0 :                 li3 = t1;
     523           0 :                 y0 += h;
     524           0 :                 h *= -1;
     525           0 :                 break;
     526             :         case 6: //FYR90
     527           0 :                 t = vertex_dirs[0];
     528           0 :                 vertex_dirs[0] = vertex_dirs[3];
     529           0 :                 vertex_dirs[3] = vertex_dirs[2];
     530           0 :                 vertex_dirs[2] = vertex_dirs[1];
     531           0 :                 vertex_dirs[1] = t;
     532           0 :                 t1  = li0;
     533           0 :                 li0 = li3;
     534           0 :                 li3 = li2;
     535           0 :                 li2 = li1;
     536           0 :                 li1 = t1;
     537           0 :                 x0 += w;
     538           0 :                 w *= -1;
     539           0 :                 break;
     540             :         case 7: //FYR270
     541           0 :                 t = vertex_dirs[0];
     542           0 :                 vertex_dirs[0] = vertex_dirs[1];
     543           0 :                 vertex_dirs[1] = vertex_dirs[2];
     544           0 :                 vertex_dirs[2] = vertex_dirs[3];
     545           0 :                 vertex_dirs[3] = t;
     546           0 :                 t1  = li0;
     547           0 :                 li0 = li1;
     548           0 :                 li1 = li2;
     549           0 :                 li2 = li3;
     550           0 :                 li3 = t1;
     551           0 :                 x0 += w;
     552           0 :                 w *= -1;
     553           0 :                 break;
     554             :         case 8: //FX
     555           0 :                 y0 += h;
     556           0 :                 h *= -1;
     557           0 :                 break;
     558             :         case 9: //FY
     559           0 :                 x0 += w;
     560           0 :                 w *= -1;
     561           0 :                 break;
     562             :         default:
     563           0 :                 break;
     564             :         }
     565             : 
     566     3871105 :         for(u16 i=0; i<4; i++)
     567             :         {
     568    12387536 :                 vertex_pos[i] = v3f(
     569     3096884 :                                 BS/2*vertex_dirs[i].X,
     570     3096884 :                                 BS/2*vertex_dirs[i].Y,
     571     3096884 :                                 BS/2*vertex_dirs[i].Z
     572     3096884 :                 );
     573             :         }
     574             : 
     575     3871105 :         for(u16 i=0; i<4; i++)
     576             :         {
     577     3096884 :                 vertex_pos[i].X *= scale.X;
     578     3096884 :                 vertex_pos[i].Y *= scale.Y;
     579     3096884 :                 vertex_pos[i].Z *= scale.Z;
     580     3096884 :                 vertex_pos[i] += pos;
     581             :         }
     582             : 
     583      774221 :         f32 abs_scale = 1.0;
     584      774221 :         if     (scale.X < 0.999 || scale.X > 1.001) abs_scale = scale.X;
     585      706252 :         else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y;
     586      706252 :         else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z;
     587             : 
     588      774221 :         v3f normal(dir.X, dir.Y, dir.Z);
     589             : 
     590      774221 :         u8 alpha = tile.alpha;
     591             : 
     592      774221 :         dest.push_back(FastFace());
     593             : 
     594      774221 :         FastFace& face = *dest.rbegin();
     595             : 
     596     2322663 :         face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
     597             :                         MapBlock_LightColor(alpha, li0, light_source),
     598     1548442 :                         core::vector2d<f32>(x0+w*abs_scale, y0+h));
     599     1548442 :         face.vertices[1] = video::S3DVertex(vertex_pos[1], normal,
     600             :                         MapBlock_LightColor(alpha, li1, light_source),
     601      774221 :                         core::vector2d<f32>(x0, y0+h));
     602     1548442 :         face.vertices[2] = video::S3DVertex(vertex_pos[2], normal,
     603             :                         MapBlock_LightColor(alpha, li2, light_source),
     604      774221 :                         core::vector2d<f32>(x0, y0));
     605     1548442 :         face.vertices[3] = video::S3DVertex(vertex_pos[3], normal,
     606             :                         MapBlock_LightColor(alpha, li3, light_source),
     607     1548442 :                         core::vector2d<f32>(x0+w*abs_scale, y0));
     608             : 
     609      774221 :         face.tile = tile;
     610      774221 : }
     611             : 
     612             : /*
     613             :         Nodes make a face if contents differ and solidness differs.
     614             :         Return value:
     615             :                 0: No face
     616             :                 1: Face uses m1's content
     617             :                 2: Face uses m2's content
     618             :         equivalent: Whether the blocks share the same face (eg. water and glass)
     619             : 
     620             :         TODO: Add 3: Both faces drawn with backface culling, remove equivalent
     621             : */
     622    25843456 : static u8 face_contents(content_t m1, content_t m2, bool *equivalent,
     623             :                 INodeDefManager *ndef)
     624             : {
     625    25843456 :         *equivalent = false;
     626             : 
     627    25843456 :         if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
     628           0 :                 return 0;
     629             : 
     630    25843456 :         bool contents_differ = (m1 != m2);
     631             : 
     632    25843456 :         const ContentFeatures &f1 = ndef->get(m1);
     633    25843456 :         const ContentFeatures &f2 = ndef->get(m2);
     634             : 
     635             :         // Contents don't differ for different forms of same liquid
     636    25843456 :         if(f1.sameLiquid(f2))
     637     1363820 :                 contents_differ = false;
     638             : 
     639    25843456 :         u8 c1 = f1.solidness;
     640    25843456 :         u8 c2 = f2.solidness;
     641             : 
     642    25843456 :         bool solidness_differs = (c1 != c2);
     643    25843456 :         bool makes_face = contents_differ && solidness_differs;
     644             : 
     645    25843456 :         if(makes_face == false)
     646    24985020 :                 return 0;
     647             : 
     648      858436 :         if(c1 == 0)
     649      273361 :                 c1 = f1.visual_solidness;
     650      858436 :         if(c2 == 0)
     651      443341 :                 c2 = f2.visual_solidness;
     652             : 
     653      858436 :         if(c1 == c2){
     654         333 :                 *equivalent = true;
     655             :                 // If same solidness, liquid takes precense
     656         333 :                 if(f1.isLiquid())
     657          83 :                         return 1;
     658         250 :                 if(f2.isLiquid())
     659         250 :                         return 2;
     660             :         }
     661             : 
     662      858103 :         if(c1 > c2)
     663      541426 :                 return 1;
     664             :         else
     665      316677 :                 return 2;
     666             : }
     667             : 
     668             : /*
     669             :         Gets nth node tile (0 <= n <= 5).
     670             : */
     671     1110732 : TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
     672             : {
     673     1110732 :         INodeDefManager *ndef = data->m_gamedef->ndef();
     674     1110732 :         TileSpec spec = ndef->get(mn).tiles[tileindex];
     675             :         // Apply temporary crack
     676     1110732 :         if (p == data->m_crack_pos_relative)
     677           0 :                 spec.material_flags |= MATERIAL_FLAG_CRACK;
     678     1110732 :         return spec;
     679             : }
     680             : 
     681             : /*
     682             :         Gets node tile given a face direction.
     683             : */
     684      947744 : TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
     685             : {
     686      947744 :         INodeDefManager *ndef = data->m_gamedef->ndef();
     687             : 
     688             :         // Direction must be (1,0,0), (-1,0,0), (0,1,0), (0,-1,0),
     689             :         // (0,0,1), (0,0,-1) or (0,0,0)
     690             :         assert(dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z <= 1);
     691             : 
     692             :         // Convert direction to single integer for table lookup
     693             :         //  0 = (0,0,0)
     694             :         //  1 = (1,0,0)
     695             :         //  2 = (0,1,0)
     696             :         //  3 = (0,0,1)
     697             :         //  4 = invalid, treat as (0,0,0)
     698             :         //  5 = (0,0,-1)
     699             :         //  6 = (0,-1,0)
     700             :         //  7 = (-1,0,0)
     701      947744 :         u8 dir_i = ((dir.X + 2 * dir.Y + 3 * dir.Z) & 7)*2;
     702             : 
     703             :         // Get rotation for things like chests
     704      947744 :         u8 facedir = mn.getFaceDir(ndef);
     705             : 
     706             :         static const u16 dir_to_tile[24 * 16] =
     707             :         {
     708             :                 // 0     +X    +Y    +Z           -Z    -Y    -X   ->   value=tile,rotation
     709             :                    0,0,  2,0 , 0,0 , 4,0 ,  0,0,  5,0 , 1,0 , 3,0 ,  // rotate around y+ 0 - 3
     710             :                    0,0,  4,0 , 0,3 , 3,0 ,  0,0,  2,0 , 1,1 , 5,0 ,
     711             :                    0,0,  3,0 , 0,2 , 5,0 ,  0,0,  4,0 , 1,2 , 2,0 ,
     712             :                    0,0,  5,0 , 0,1 , 2,0 ,  0,0,  3,0 , 1,3 , 4,0 ,
     713             : 
     714             :                    0,0,  2,3 , 5,0 , 0,2 ,  0,0,  1,0 , 4,2 , 3,1 ,  // rotate around z+ 4 - 7
     715             :                    0,0,  4,3 , 2,0 , 0,1 ,  0,0,  1,1 , 3,2 , 5,1 ,
     716             :                    0,0,  3,3 , 4,0 , 0,0 ,  0,0,  1,2 , 5,2 , 2,1 ,
     717             :                    0,0,  5,3 , 3,0 , 0,3 ,  0,0,  1,3 , 2,2 , 4,1 ,
     718             : 
     719             :                    0,0,  2,1 , 4,2 , 1,2 ,  0,0,  0,0 , 5,0 , 3,3 ,  // rotate around z- 8 - 11
     720             :                    0,0,  4,1 , 3,2 , 1,3 ,  0,0,  0,3 , 2,0 , 5,3 ,
     721             :                    0,0,  3,1 , 5,2 , 1,0 ,  0,0,  0,2 , 4,0 , 2,3 ,
     722             :                    0,0,  5,1 , 2,2 , 1,1 ,  0,0,  0,1 , 3,0 , 4,3 ,
     723             : 
     724             :                    0,0,  0,3 , 3,3 , 4,1 ,  0,0,  5,3 , 2,3 , 1,3 ,  // rotate around x+ 12 - 15
     725             :                    0,0,  0,2 , 5,3 , 3,1 ,  0,0,  2,3 , 4,3 , 1,0 ,
     726             :                    0,0,  0,1 , 2,3 , 5,1 ,  0,0,  4,3 , 3,3 , 1,1 ,
     727             :                    0,0,  0,0 , 4,3 , 2,1 ,  0,0,  3,3 , 5,3 , 1,2 ,
     728             : 
     729             :                    0,0,  1,1 , 2,1 , 4,3 ,  0,0,  5,1 , 3,1 , 0,1 ,  // rotate around x- 16 - 19
     730             :                    0,0,  1,2 , 4,1 , 3,3 ,  0,0,  2,1 , 5,1 , 0,0 ,
     731             :                    0,0,  1,3 , 3,1 , 5,3 ,  0,0,  4,1 , 2,1 , 0,3 ,
     732             :                    0,0,  1,0 , 5,1 , 2,3 ,  0,0,  3,1 , 4,1 , 0,2 ,
     733             : 
     734             :                    0,0,  3,2 , 1,2 , 4,2 ,  0,0,  5,2 , 0,2 , 2,2 ,  // rotate around y- 20 - 23
     735             :                    0,0,  5,2 , 1,3 , 3,2 ,  0,0,  2,2 , 0,1 , 4,2 ,
     736             :                    0,0,  2,2 , 1,0 , 5,2 ,  0,0,  4,2 , 0,0 , 3,2 ,
     737             :                    0,0,  4,2 , 1,1 , 2,2 ,  0,0,  3,2 , 0,3 , 5,2
     738             : 
     739             :         };
     740      947744 :         u16 tile_index=facedir*16 + dir_i;
     741      947744 :         TileSpec spec = getNodeTileN(mn, p, dir_to_tile[tile_index], data);
     742      947744 :         spec.rotation=dir_to_tile[tile_index + 1];
     743      947744 :         spec.texture = data->m_gamedef->tsrc()->getTexture(spec.texture_id);
     744      947744 :         return spec;
     745             : }
     746             : 
     747    26296320 : static void getTileInfo(
     748             :                 // Input:
     749             :                 MeshMakeData *data,
     750             :                 const v3s16 &p,
     751             :                 const v3s16 &face_dir,
     752             :                 // Output:
     753             :                 bool &makes_face,
     754             :                 v3s16 &p_corrected,
     755             :                 v3s16 &face_dir_corrected,
     756             :                 u16 *lights,
     757             :                 TileSpec &tile,
     758             :                 u8 &light_source
     759             :         )
     760             : {
     761    26296320 :         VoxelManipulator &vmanip = data->m_vmanip;
     762    26296320 :         INodeDefManager *ndef = data->m_gamedef->ndef();
     763    26296320 :         v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
     764             : 
     765    26296320 :         MapNode &n0 = vmanip.getNodeRefUnsafe(blockpos_nodes + p);
     766             : 
     767             :         // Don't even try to get n1 if n0 is already CONTENT_IGNORE
     768    26296320 :         if (n0.getContent() == CONTENT_IGNORE) {
     769           0 :                 makes_face = false;
     770           0 :                 return;
     771             :         }
     772             : 
     773    26296320 :         const MapNode &n1 = vmanip.getNodeRefUnsafeCheckFlags(blockpos_nodes + p + face_dir);
     774             : 
     775    26296320 :         if (n1.getContent() == CONTENT_IGNORE) {
     776      452864 :                 makes_face = false;
     777      452864 :                 return;
     778             :         }
     779             : 
     780             :         // This is hackish
     781    25843456 :         bool equivalent = false;
     782    25843456 :         u8 mf = face_contents(n0.getContent(), n1.getContent(),
     783    25843456 :                         &equivalent, ndef);
     784             : 
     785    25843456 :         if(mf == 0)
     786             :         {
     787    24985020 :                 makes_face = false;
     788    24985020 :                 return;
     789             :         }
     790             : 
     791      858436 :         makes_face = true;
     792             : 
     793      858436 :         if(mf == 1)
     794             :         {
     795      541509 :                 tile = getNodeTile(n0, p, face_dir, data);
     796      541509 :                 p_corrected = p;
     797      541509 :                 face_dir_corrected = face_dir;
     798      541509 :                 light_source = ndef->get(n0).light_source;
     799             :         }
     800             :         else
     801             :         {
     802      316927 :                 tile = getNodeTile(n1, p + face_dir, -face_dir, data);
     803      316927 :                 p_corrected = p + face_dir;
     804      316927 :                 face_dir_corrected = -face_dir;
     805      316927 :                 light_source = ndef->get(n1).light_source;
     806             :         }
     807             : 
     808             :         // eg. water and glass
     809      858436 :         if(equivalent)
     810         333 :                 tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
     811             : 
     812      858436 :         if(data->m_smooth_lighting == false)
     813             :         {
     814          24 :                 lights[0] = lights[1] = lights[2] = lights[3] =
     815          24 :                                 getFaceLight(n0, n1, face_dir, ndef);
     816             :         }
     817             :         else
     818             :         {
     819      858430 :                 v3s16 vertex_dirs[4];
     820      858430 :                 getNodeVertexDirs(face_dir_corrected, vertex_dirs);
     821     4292150 :                 for(u16 i=0; i<4; i++)
     822             :                 {
     823    13734880 :                         lights[i] = getSmoothLight(
     824     6867440 :                                         blockpos_nodes + p_corrected,
     825     6867440 :                                         vertex_dirs[i], data);
     826             :                 }
     827             :         }
     828             : 
     829      858436 :         return;
     830             : }
     831             : 
     832             : /*
     833             :         startpos:
     834             :         translate_dir: unit vector with only one of x, y or z
     835             :         face_dir: unit vector with only one of x, y or z
     836             : */
     837     1643520 : static void updateFastFaceRow(
     838             :                 MeshMakeData *data,
     839             :                 v3s16 startpos,
     840             :                 v3s16 translate_dir,
     841             :                 v3f translate_dir_f,
     842             :                 v3s16 face_dir,
     843             :                 v3f face_dir_f,
     844             :                 std::vector<FastFace> &dest)
     845             : {
     846     1643520 :         v3s16 p = startpos;
     847             : 
     848     1643520 :         u16 continuous_tiles_count = 0;
     849             : 
     850     1643520 :         bool makes_face = false;
     851     1643520 :         v3s16 p_corrected;
     852     1643520 :         v3s16 face_dir_corrected;
     853     1643520 :         u16 lights[4] = {0,0,0,0};
     854     3287040 :         TileSpec tile;
     855     1643520 :         u8 light_source = 0;
     856             :         getTileInfo(data, p, face_dir,
     857             :                         makes_face, p_corrected, face_dir_corrected,
     858     1643520 :                         lights, tile, light_source);
     859             : 
     860    27939840 :         for(u16 j=0; j<MAP_BLOCKSIZE; j++)
     861             :         {
     862             :                 // If tiling can be done, this is set to false in the next step
     863    26296320 :                 bool next_is_different = true;
     864             : 
     865    26296320 :                 v3s16 p_next;
     866             : 
     867    26296320 :                 bool next_makes_face = false;
     868    26296320 :                 v3s16 next_p_corrected;
     869    26296320 :                 v3s16 next_face_dir_corrected;
     870    26296320 :                 u16 next_lights[4] = {0,0,0,0};
     871    52592640 :                 TileSpec next_tile;
     872    26296320 :                 u8 next_light_source = 0;
     873             : 
     874             :                 // If at last position, there is nothing to compare to and
     875             :                 // the face must be drawn anyway
     876    26296320 :                 if(j != MAP_BLOCKSIZE - 1)
     877             :                 {
     878    24652800 :                         p_next = p + translate_dir;
     879             : 
     880             :                         getTileInfo(data, p_next, face_dir,
     881             :                                         next_makes_face, next_p_corrected,
     882             :                                         next_face_dir_corrected, next_lights,
     883    24652800 :                                         next_tile, next_light_source);
     884             : 
     885    74702262 :                         if(next_makes_face == makes_face
     886    72470676 :                                         && next_p_corrected == p_corrected + translate_dir
     887      367107 :                                         && next_face_dir_corrected == face_dir_corrected
     888      367107 :                                         && next_lights[0] == lights[0]
     889      134854 :                                         && next_lights[1] == lights[1]
     890      100124 :                                         && next_lights[2] == lights[2]
     891       93503 :                                         && next_lights[3] == lights[3]
     892       90621 :                                         && next_tile == tile
     893       84246 :                                         && tile.rotation == 0
     894    49389815 :                                         && next_light_source == light_source)
     895             :                         {
     896       84215 :                                 next_is_different = false;
     897             :                         }
     898             :                         else{
     899             :                                 /*if(makes_face){
     900             :                                         g_profiler->add("Meshgen: diff: next_makes_face != makes_face",
     901             :                                                         next_makes_face != makes_face ? 1 : 0);
     902             :                                         g_profiler->add("Meshgen: diff: n_p_corr != p_corr + t_dir",
     903             :                                                         (next_p_corrected != p_corrected + translate_dir) ? 1 : 0);
     904             :                                         g_profiler->add("Meshgen: diff: next_f_dir_corr != f_dir_corr",
     905             :                                                         next_face_dir_corrected != face_dir_corrected ? 1 : 0);
     906             :                                         g_profiler->add("Meshgen: diff: next_lights[] != lights[]",
     907             :                                                         (next_lights[0] != lights[0] ||
     908             :                                                         next_lights[0] != lights[0] ||
     909             :                                                         next_lights[0] != lights[0] ||
     910             :                                                         next_lights[0] != lights[0]) ? 1 : 0);
     911             :                                         g_profiler->add("Meshgen: diff: !(next_tile == tile)",
     912             :                                                         !(next_tile == tile) ? 1 : 0);
     913             :                                 }*/
     914             :                         }
     915             :                         /*g_profiler->add("Meshgen: Total faces checked", 1);
     916             :                         if(makes_face)
     917             :                                 g_profiler->add("Meshgen: Total makes_face checked", 1);*/
     918             :                 } else {
     919             :                         /*if(makes_face)
     920             :                                 g_profiler->add("Meshgen: diff: last position", 1);*/
     921             :                 }
     922             : 
     923    26296320 :                 continuous_tiles_count++;
     924             : 
     925    26296320 :                 if(next_is_different)
     926             :                 {
     927             :                         /*
     928             :                                 Create a face if there should be one
     929             :                         */
     930    26212105 :                         if(makes_face)
     931             :                         {
     932             :                                 // Floating point conversion of the position vector
     933      774221 :                                 v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z);
     934             :                                 // Center point of face (kind of)
     935      774221 :                                 v3f sp = pf - ((f32)continuous_tiles_count / 2.0 - 0.5) * translate_dir_f;
     936      774221 :                                 if(continuous_tiles_count != 1)
     937       84215 :                                         sp += translate_dir_f;
     938      774221 :                                 v3f scale(1,1,1);
     939             : 
     940      774221 :                                 if(translate_dir.X != 0) {
     941      554242 :                                         scale.X = continuous_tiles_count;
     942             :                                 }
     943      774221 :                                 if(translate_dir.Y != 0) {
     944           0 :                                         scale.Y = continuous_tiles_count;
     945             :                                 }
     946      774221 :                                 if(translate_dir.Z != 0) {
     947      219979 :                                         scale.Z = continuous_tiles_count;
     948             :                                 }
     949             : 
     950     1548442 :                                 makeFastFace(tile, lights[0], lights[1], lights[2], lights[3],
     951             :                                                 sp, face_dir_corrected, scale, light_source,
     952      774221 :                                                 dest);
     953             : 
     954      774221 :                                 g_profiler->avg("Meshgen: faces drawn by tiling", 0);
     955      858436 :                                 for(int i = 1; i < continuous_tiles_count; i++){
     956       84215 :                                         g_profiler->avg("Meshgen: faces drawn by tiling", 1);
     957             :                                 }
     958             :                         }
     959             : 
     960    26212105 :                         continuous_tiles_count = 0;
     961             : 
     962    26212105 :                         makes_face = next_makes_face;
     963    26212105 :                         p_corrected = next_p_corrected;
     964    26212105 :                         face_dir_corrected = next_face_dir_corrected;
     965    26212105 :                         lights[0] = next_lights[0];
     966    26212105 :                         lights[1] = next_lights[1];
     967    26212105 :                         lights[2] = next_lights[2];
     968    26212105 :                         lights[3] = next_lights[3];
     969    26212105 :                         tile = next_tile;
     970    26212105 :                         light_source = next_light_source;
     971             :                 }
     972             : 
     973    26296320 :                 p = p_next;
     974             :         }
     975     1643520 : }
     976             : 
     977        2140 : static void updateAllFastFaceRows(MeshMakeData *data,
     978             :                 std::vector<FastFace> &dest)
     979             : {
     980             :         /*
     981             :                 Go through every y,z and get top(y+) faces in rows of x+
     982             :         */
     983       36380 :         for(s16 y = 0; y < MAP_BLOCKSIZE; y++) {
     984      582080 :                 for(s16 z = 0; z < MAP_BLOCKSIZE; z++) {
     985     1095680 :                         updateFastFaceRow(data,
     986             :                                         v3s16(0,y,z),
     987             :                                         v3s16(1,0,0), //dir
     988             :                                         v3f  (1,0,0),
     989             :                                         v3s16(0,1,0), //face dir
     990             :                                         v3f  (0,1,0),
     991      547840 :                                         dest);
     992             :                 }
     993             :         }
     994             : 
     995             :         /*
     996             :                 Go through every x,y and get right(x+) faces in rows of z+
     997             :         */
     998       36380 :         for(s16 x = 0; x < MAP_BLOCKSIZE; x++) {
     999      582080 :                 for(s16 y = 0; y < MAP_BLOCKSIZE; y++) {
    1000     1095680 :                         updateFastFaceRow(data,
    1001             :                                         v3s16(x,y,0),
    1002             :                                         v3s16(0,0,1), //dir
    1003             :                                         v3f  (0,0,1),
    1004             :                                         v3s16(1,0,0), //face dir
    1005             :                                         v3f  (1,0,0),
    1006      547840 :                                         dest);
    1007             :                 }
    1008             :         }
    1009             : 
    1010             :         /*
    1011             :                 Go through every y,z and get back(z+) faces in rows of x+
    1012             :         */
    1013       36380 :         for(s16 z = 0; z < MAP_BLOCKSIZE; z++) {
    1014      582080 :                 for(s16 y = 0; y < MAP_BLOCKSIZE; y++) {
    1015     1095680 :                         updateFastFaceRow(data,
    1016             :                                         v3s16(0,y,z),
    1017             :                                         v3s16(1,0,0), //dir
    1018             :                                         v3f  (1,0,0),
    1019             :                                         v3s16(0,0,1), //face dir
    1020             :                                         v3f  (0,0,1),
    1021      547840 :                                         dest);
    1022             :                 }
    1023             :         }
    1024        2140 : }
    1025             : 
    1026             : /*
    1027             :         MapBlockMesh
    1028             : */
    1029             : 
    1030        2140 : MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
    1031           0 :         m_mesh(new scene::SMesh()),
    1032        2140 :         m_minimap_mapblock(new MinimapMapblock),
    1033        2140 :         m_gamedef(data->m_gamedef),
    1034        2140 :         m_tsrc(m_gamedef->getTextureSource()),
    1035        2140 :         m_shdrsrc(m_gamedef->getShaderSource()),
    1036             :         m_animation_force_timer(0), // force initial animation
    1037             :         m_last_crack(-1),
    1038             :         m_crack_materials(),
    1039             :         m_highlighted_materials(),
    1040             :         m_last_daynight_ratio((u32) -1),
    1041       10700 :         m_daynight_diffs()
    1042             : {
    1043        2140 :         m_enable_shaders = data->m_use_shaders;
    1044        2140 :         m_enable_highlighting = g_settings->getBool("enable_node_highlighting");
    1045             : 
    1046        2140 :         if (g_settings->getBool("enable_minimap")) {
    1047        2140 :                 v3s16 blockpos_nodes = data->m_blockpos * MAP_BLOCKSIZE;
    1048       36380 :                 for(s16 x = 0; x < MAP_BLOCKSIZE; x++) {
    1049      582080 :                         for(s16 z = 0; z < MAP_BLOCKSIZE; z++) {
    1050      547840 :                                 s16 air_count = 0;
    1051      547840 :                                 bool surface_found = false;
    1052      547840 :                                 MinimapPixel* minimap_pixel = &m_minimap_mapblock->data[x + z * MAP_BLOCKSIZE];
    1053     9313280 :                                 for(s16 y = MAP_BLOCKSIZE -1; y > -1; y--) {
    1054     8765440 :                                         v3s16 p(x, y, z);
    1055     8765440 :                                         MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
    1056     8765440 :                                         if (!surface_found && n.getContent() != CONTENT_AIR) {
    1057      392197 :                                                 minimap_pixel->height = y;
    1058      392197 :                                                 minimap_pixel->id = n.getContent();
    1059      392197 :                                                 surface_found = true;
    1060     8373243 :                                         } else if (n.getContent() == CONTENT_AIR) {
    1061     3677159 :                                                 air_count++;
    1062             :                                         }
    1063             :                                 }
    1064      547840 :                                 if (!surface_found) {
    1065      155643 :                                         minimap_pixel->id = CONTENT_AIR;
    1066             :                                 }
    1067      547840 :                                 minimap_pixel->air_count = air_count;
    1068             :                         }
    1069             :                 }
    1070             :         }
    1071             : 
    1072             :         // 4-21ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
    1073             :         // 24-155ms for MAP_BLOCKSIZE=32  (NOTE: probably outdated)
    1074             :         //TimeTaker timer1("MapBlockMesh()");
    1075             : 
    1076        4280 :         std::vector<FastFace> fastfaces_new;
    1077        2140 :         fastfaces_new.reserve(512);
    1078             : 
    1079             :         /*
    1080             :                 We are including the faces of the trailing edges of the block.
    1081             :                 This means that when something changes, the caller must
    1082             :                 also update the meshes of the blocks at the leading edges.
    1083             : 
    1084             :                 NOTE: This is the slowest part of this method.
    1085             :         */
    1086             :         {
    1087             :                 // 4-23ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
    1088             :                 //TimeTaker timer2("updateAllFastFaceRows()");
    1089        2140 :                 updateAllFastFaceRows(data, fastfaces_new);
    1090             :         }
    1091             :         // End of slow part
    1092             : 
    1093             :         /*
    1094             :                 Convert FastFaces to MeshCollector
    1095             :         */
    1096             : 
    1097        4280 :         MeshCollector collector;
    1098             : 
    1099             :         {
    1100             :                 // avg 0ms (100ms spikes when loading textures the first time)
    1101             :                 // (NOTE: probably outdated)
    1102             :                 //TimeTaker timer2("MeshCollector building");
    1103             : 
    1104      776361 :                 for(u32 i=0; i<fastfaces_new.size(); i++)
    1105             :                 {
    1106      774221 :                         FastFace &f = fastfaces_new[i];
    1107             : 
    1108      774221 :                         const u16 indices[] = {0,1,2,2,3,0};
    1109      774221 :                         const u16 indices_alternate[] = {0,1,3,2,3,1};
    1110             : 
    1111      774221 :                         if(f.tile.texture == NULL)
    1112           0 :                                 continue;
    1113             : 
    1114      774221 :                         const u16 *indices_p = indices;
    1115             : 
    1116             :                         /*
    1117             :                                 Revert triangles for nicer looking gradient if vertices
    1118             :                                 1 and 3 have same color or 0 and 2 have different color.
    1119             :                                 getRed() is the day color.
    1120             :                         */
    1121     1548442 :                         if(f.vertices[0].Color.getRed() != f.vertices[2].Color.getRed()
    1122      774221 :                                         || f.vertices[1].Color.getRed() == f.vertices[3].Color.getRed())
    1123      738136 :                                 indices_p = indices_alternate;
    1124             : 
    1125      774221 :                         collector.append(f.tile, f.vertices, 4, indices_p, 6);
    1126             :                 }
    1127             :         }
    1128             : 
    1129             :         /*
    1130             :                 Add special graphics:
    1131             :                 - torches
    1132             :                 - flowing water
    1133             :                 - fences
    1134             :                 - whatever
    1135             :         */
    1136             : 
    1137        2140 :         mapblock_mesh_generate_special(data, collector);
    1138             : 
    1139        2140 :         m_highlight_mesh_color = data->m_highlight_mesh_color;
    1140             : 
    1141             :         /*
    1142             :                 Convert MeshCollector to SMesh
    1143             :         */
    1144             : 
    1145       33252 :         for(u32 i = 0; i < collector.prebuffers.size(); i++)
    1146             :         {
    1147       31112 :                 PreMeshBuffer &p = collector.prebuffers[i];
    1148             : 
    1149             :                 // Generate animation data
    1150             :                 // - Cracks
    1151       31112 :                 if(p.tile.material_flags & MATERIAL_FLAG_CRACK)
    1152             :                 {
    1153             :                         // Find the texture name plus ^[crack:N:
    1154           0 :                         std::ostringstream os(std::ios::binary);
    1155           0 :                         os<<m_tsrc->getTextureName(p.tile.texture_id)<<"^[crack";
    1156           0 :                         if(p.tile.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
    1157           0 :                                 os<<"o";  // use ^[cracko
    1158           0 :                         os<<":"<<(u32)p.tile.animation_frame_count<<":";
    1159           0 :                         m_crack_materials.insert(std::make_pair(i, os.str()));
    1160             :                         // Replace tile texture with the cracked one
    1161           0 :                         p.tile.texture = m_tsrc->getTextureForMesh(
    1162           0 :                                         os.str()+"0",
    1163           0 :                                         &p.tile.texture_id);
    1164             :                 }
    1165             :                 // - Texture animation
    1166       31112 :                 if(p.tile.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
    1167             :                 {
    1168             :                         // Add to MapBlockMesh in order to animate these tiles
    1169        1463 :                         m_animation_tiles[i] = p.tile;
    1170        1463 :                         m_animation_frames[i] = 0;
    1171        1463 :                         if(g_settings->getBool("desynchronize_mapblock_texture_animation")){
    1172             :                                 // Get starting position from noise
    1173        5852 :                                 m_animation_frame_offsets[i] = 100000 * (2.0 + noise3d(
    1174        2926 :                                                 data->m_blockpos.X, data->m_blockpos.Y,
    1175        2926 :                                                 data->m_blockpos.Z, 0));
    1176             :                         } else {
    1177             :                                 // Play all synchronized
    1178           0 :                                 m_animation_frame_offsets[i] = 0;
    1179             :                         }
    1180             :                         // Replace tile texture with the first animation frame
    1181        1463 :                         FrameSpec animation_frame = p.tile.frames[0];
    1182        1463 :                         p.tile.texture = animation_frame.texture;
    1183             :                 }
    1184             : 
    1185       31112 :                 if(m_enable_highlighting && p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED)
    1186          45 :                         m_highlighted_materials.push_back(i);   
    1187             : 
    1188     7226795 :                 for(u32 j = 0; j < p.vertices.size(); j++)
    1189             :                 {
    1190     7195683 :                         video::S3DVertexTangents *vertex = &p.vertices[j];
    1191             :                         // Note applyFacesShading second parameter is precalculated sqrt
    1192             :                         // value for speed improvement
    1193             :                         // Skip it for lightsources and top faces.
    1194     7195683 :                         video::SColor &vc = vertex->Color;
    1195     7195683 :                         if (!vc.getBlue()) {
    1196     7111615 :                                 if (vertex->Normal.Y < -0.5) {
    1197      965534 :                                         applyFacesShading (vc, 0.447213);
    1198     6146081 :                                 } else if (vertex->Normal.X > 0.5) {
    1199     1044339 :                                         applyFacesShading (vc, 0.670820);
    1200     5101742 :                                 } else if (vertex->Normal.X < -0.5) {
    1201     1038918 :                                         applyFacesShading (vc, 0.670820);
    1202     4062824 :                                 } else if (vertex->Normal.Z > 0.5) {
    1203      970406 :                                         applyFacesShading (vc, 0.836660);
    1204     3092418 :                                 } else if (vertex->Normal.Z < -0.5) {
    1205      968712 :                                         applyFacesShading (vc, 0.836660);
    1206             :                                 }
    1207             :                         }
    1208     7195683 :                         if(!m_enable_shaders)
    1209             :                         {
    1210             :                                 // - Classic lighting (shaders handle this by themselves)
    1211             :                                 // Set initial real color and store for later updates
    1212          24 :                                 u8 day = vc.getRed();
    1213          24 :                                 u8 night = vc.getGreen();
    1214          24 :                                 finalColorBlend(vc, day, night, 1000);
    1215          24 :                                 if(day != night)
    1216          24 :                                         m_daynight_diffs[i][j] = std::make_pair(day, night);
    1217             :                         }
    1218             :                 }
    1219             : 
    1220             :                 // Create material
    1221       62224 :                 video::SMaterial material;
    1222       31112 :                 material.setFlag(video::EMF_LIGHTING, false);
    1223       31112 :                 material.setFlag(video::EMF_BACK_FACE_CULLING, true);
    1224       31112 :                 material.setFlag(video::EMF_BILINEAR_FILTER, false);
    1225       31112 :                 material.setFlag(video::EMF_FOG_ENABLE, true);
    1226       31112 :                 material.setTexture(0, p.tile.texture);
    1227             : 
    1228       31112 :                 if (p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED) {
    1229          45 :                         material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
    1230             :                 } else {
    1231       31067 :                         if (m_enable_shaders) {
    1232       31066 :                                 material.MaterialType = m_shdrsrc->getShaderInfo(p.tile.shader_id).material;
    1233       31066 :                                 p.tile.applyMaterialOptionsWithShaders(material);
    1234       31066 :                                 if (p.tile.normal_texture) {
    1235           0 :                                         material.setTexture(1, p.tile.normal_texture);
    1236           0 :                                         material.setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
    1237             :                                 } else {
    1238       31066 :                                         material.setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
    1239             :                                 }
    1240             :                         } else {
    1241           1 :                                 p.tile.applyMaterialOptions(material);
    1242             :                         }
    1243             :                 }
    1244             : 
    1245             :         // Create meshbuffer
    1246       31112 :         scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
    1247             :         // Set material
    1248       31112 :         buf->Material = material;
    1249             :         // Add to mesh
    1250       31112 :         m_mesh->addMeshBuffer(buf);
    1251             :         // Mesh grabbed it
    1252       31112 :         buf->drop();
    1253       62224 :         buf->append(&p.vertices[0], p.vertices.size(),
    1254       93336 :                 &p.indices[0], p.indices.size());
    1255             : }
    1256        2140 :         m_camera_offset = camera_offset;
    1257             : 
    1258             :         /*
    1259             :                 Do some stuff to the mesh
    1260             :         */
    1261             : 
    1262        2140 :         translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
    1263             : 
    1264        2140 :         if (m_enable_shaders) {
    1265        2139 :                 scene::IMeshManipulator* meshmanip = m_gamedef->getSceneManager()->getMeshManipulator();
    1266        2139 :                 meshmanip->recalculateTangents(m_mesh, true, false, false);
    1267             :         }
    1268             : 
    1269        2140 :         if(m_mesh)
    1270             :         {
    1271             : #if 0
    1272             :                 // Usually 1-700 faces and 1-7 materials
    1273             :                 std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
    1274             :                                 <<"and uses "<<m_mesh->getMeshBufferCount()
    1275             :                                 <<" materials (meshbuffers)"<<std::endl;
    1276             : #endif
    1277             : 
    1278             :                 // Use VBO for mesh (this just would set this for ever buffer)
    1279             :                 // This will lead to infinite memory usage because or irrlicht.
    1280             :                 //m_mesh->setHardwareMappingHint(scene::EHM_STATIC);
    1281             : 
    1282             :                 /*
    1283             :                         NOTE: If that is enabled, some kind of a queue to the main
    1284             :                         thread should be made which would call irrlicht to delete
    1285             :                         the hardware buffer and then delete the mesh
    1286             :                 */
    1287             :         }
    1288             : 
    1289             :         //std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
    1290             : 
    1291             :         // Check if animation is required for this mesh
    1292             :         m_has_animation =
    1293        4280 :                 !m_crack_materials.empty() ||
    1294        4279 :                 !m_daynight_diffs.empty() ||
    1295        5416 :                 !m_animation_tiles.empty() ||
    1296        3277 :                 !m_highlighted_materials.empty();
    1297        2140 : }
    1298             : 
    1299        4280 : MapBlockMesh::~MapBlockMesh()
    1300             : {
    1301        2140 :         m_mesh->drop();
    1302        2140 :         m_mesh = NULL;
    1303        2140 : }
    1304             : 
    1305      148401 : bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio)
    1306             : {
    1307      148401 :         if(!m_has_animation)
    1308             :         {
    1309       75289 :                 m_animation_force_timer = 100000;
    1310       75289 :                 return false;
    1311             :         }
    1312             : 
    1313       73112 :         m_animation_force_timer = myrand_range(5, 100);
    1314             : 
    1315             :         // Cracks
    1316       73112 :         if(crack != m_last_crack)
    1317             :         {
    1318           0 :                 for(std::map<u32, std::string>::iterator
    1319           0 :                                 i = m_crack_materials.begin();
    1320           0 :                                 i != m_crack_materials.end(); i++)
    1321             :                 {
    1322           0 :                         scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
    1323           0 :                         std::string basename = i->second;
    1324             : 
    1325             :                         // Create new texture name from original
    1326           0 :                         std::ostringstream os;
    1327           0 :                         os<<basename<<crack;
    1328           0 :                         u32 new_texture_id = 0;
    1329             :                         video::ITexture *new_texture =
    1330           0 :                                 m_tsrc->getTextureForMesh(os.str(), &new_texture_id);
    1331           0 :                         buf->getMaterial().setTexture(0, new_texture);
    1332             : 
    1333             :                         // If the current material is also animated,
    1334             :                         // update animation info
    1335             :                         std::map<u32, TileSpec>::iterator anim_iter =
    1336           0 :                                 m_animation_tiles.find(i->first);
    1337           0 :                         if(anim_iter != m_animation_tiles.end()){
    1338           0 :                                 TileSpec &tile = anim_iter->second;
    1339           0 :                                 tile.texture = new_texture;
    1340           0 :                                 tile.texture_id = new_texture_id;
    1341             :                                 // force animation update
    1342           0 :                                 m_animation_frames[i->first] = -1;
    1343             :                         }
    1344             :                 }
    1345             : 
    1346           0 :                 m_last_crack = crack;
    1347             :         }
    1348             : 
    1349             :         // Texture animation
    1350      451018 :         for(std::map<u32, TileSpec>::iterator
    1351       73112 :                         i = m_animation_tiles.begin();
    1352      349420 :                         i != m_animation_tiles.end(); i++)
    1353             :         {
    1354      101598 :                 const TileSpec &tile = i->second;
    1355             :                 // Figure out current frame
    1356      101598 :                 int frameoffset = m_animation_frame_offsets[i->first];
    1357      101598 :                 int frame = (int)(time * 1000 / tile.animation_frame_length_ms
    1358      101598 :                                 + frameoffset) % tile.animation_frame_count;
    1359             :                 // If frame doesn't change, skip
    1360      101598 :                 if(frame == m_animation_frames[i->first])
    1361       88561 :                         continue;
    1362             : 
    1363       13037 :                 m_animation_frames[i->first] = frame;
    1364             : 
    1365       13037 :                 scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
    1366             : 
    1367       13037 :                 FrameSpec animation_frame = tile.frames[frame];
    1368       13037 :                 buf->getMaterial().setTexture(0, animation_frame.texture);
    1369       13037 :                 if (m_enable_shaders) {
    1370       13037 :                         if (animation_frame.normal_texture) {
    1371           0 :                                 buf->getMaterial().setTexture(1, animation_frame.normal_texture);
    1372           0 :                                 buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("enable_img.png"));
    1373             :                         } else {
    1374       13037 :                                 buf->getMaterial().setTexture(2, m_tsrc->getTextureForMesh("disable_img.png"));
    1375             :                         }
    1376             :                 }
    1377             :         }
    1378             : 
    1379             :         // Day-night transition
    1380       73112 :         if(!m_enable_shaders && (daynight_ratio != m_last_daynight_ratio))
    1381             :         {
    1382           0 :                 for(std::map<u32, std::map<u32, std::pair<u8, u8> > >::iterator
    1383           0 :                                 i = m_daynight_diffs.begin();
    1384           0 :                                 i != m_daynight_diffs.end(); i++)
    1385             :                 {
    1386           0 :                         scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
    1387           0 :                         video::S3DVertexTangents *vertices = (video::S3DVertexTangents *)buf->getVertices();
    1388           0 :                         for(std::map<u32, std::pair<u8, u8 > >::iterator
    1389           0 :                                         j = i->second.begin();
    1390           0 :                                         j != i->second.end(); j++)
    1391             :                         {
    1392           0 :                                 u8 day = j->second.first;
    1393           0 :                                 u8 night = j->second.second;
    1394           0 :                                 finalColorBlend(vertices[j->first].Color, day, night, daynight_ratio);
    1395             :                         }
    1396             :                 }
    1397           0 :                 m_last_daynight_ratio = daynight_ratio;
    1398             :         }
    1399             : 
    1400             :         // Node highlighting
    1401       73112 :         if (m_enable_highlighting) {
    1402       73112 :                 u8 day = m_highlight_mesh_color.getRed();
    1403       73112 :                 u8 night = m_highlight_mesh_color.getGreen();   
    1404       73112 :                 video::SColor hc;
    1405       73112 :                 finalColorBlend(hc, day, night, daynight_ratio);
    1406       73112 :                 float sin_r = 0.07 * sin(1.5 * time);
    1407       73112 :                 float sin_g = 0.07 * sin(1.5 * time + irr::core::PI * 0.5);
    1408       73112 :                 float sin_b = 0.07 * sin(1.5 * time + irr::core::PI);
    1409       73112 :                 hc.setRed(core::clamp(core::round32(hc.getRed() * (0.8 + sin_r)), 0, 255));
    1410       73112 :                 hc.setGreen(core::clamp(core::round32(hc.getGreen() * (0.8 + sin_g)), 0, 255));
    1411       73112 :                 hc.setBlue(core::clamp(core::round32(hc.getBlue() * (0.8 + sin_b)), 0, 255));
    1412             : 
    1413      147904 :                 for(std::list<u32>::iterator
    1414       73112 :                         i = m_highlighted_materials.begin();
    1415      147344 :                         i != m_highlighted_materials.end(); i++)
    1416             :                 {
    1417         560 :                         scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(*i);
    1418         560 :                         video::S3DVertexTangents *vertices = (video::S3DVertexTangents*)buf->getVertices();
    1419       14000 :                         for (u32 j = 0; j < buf->getVertexCount() ;j++)
    1420       13440 :                                 vertices[j].Color = hc;
    1421             :                 }
    1422             :         }
    1423             : 
    1424       73112 :         return true;
    1425             : }
    1426             : 
    1427       55109 : void MapBlockMesh::updateCameraOffset(v3s16 camera_offset)
    1428             : {
    1429       55109 :         if (camera_offset != m_camera_offset) {
    1430           0 :                 translateMesh(m_mesh, intToFloat(m_camera_offset-camera_offset, BS));
    1431           0 :                 m_camera_offset = camera_offset;
    1432             :         }
    1433       55109 : }
    1434             : 
    1435             : /*
    1436             :         MeshCollector
    1437             : */
    1438             : 
    1439     1440700 : void MeshCollector::append(const TileSpec &tile,
    1440             :                 const video::S3DVertex *vertices, u32 numVertices,
    1441             :                 const u16 *indices, u32 numIndices)
    1442             : {
    1443     1440700 :         if (numIndices > 65535) {
    1444           0 :                 dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
    1445           0 :                 return;
    1446             :         }
    1447             : 
    1448     1440700 :         PreMeshBuffer *p = NULL;
    1449    13122566 :         for (u32 i = 0; i < prebuffers.size(); i++) {
    1450    13099263 :                 PreMeshBuffer &pp = prebuffers[i];
    1451    13099263 :                 if (pp.tile != tile)
    1452    11681866 :                         continue;
    1453     1417397 :                 if (pp.indices.size() + numIndices > 65535)
    1454           0 :                         continue;
    1455             : 
    1456     1417397 :                 p = &pp;
    1457     1417397 :                 break;
    1458             :         }
    1459             : 
    1460     1440700 :         if (p == NULL) {
    1461       46606 :                 PreMeshBuffer pp;
    1462       23303 :                 pp.tile = tile;
    1463       23303 :                 prebuffers.push_back(pp);
    1464       23303 :                 p = &prebuffers[prebuffers.size() - 1];
    1465             :         }
    1466             : 
    1467     1440700 :         u32 vertex_count = p->vertices.size();
    1468    10084900 :         for (u32 i = 0; i < numIndices; i++) {
    1469     8644200 :                 u32 j = indices[i] + vertex_count;
    1470     8644200 :                 p->indices.push_back(j);
    1471             :         }
    1472             : 
    1473     7203500 :         for (u32 i = 0; i < numVertices; i++) {
    1474    11525600 :                 video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
    1475    17288400 :                         vertices[i].Color, vertices[i].TCoords);
    1476     5762800 :                 p->vertices.push_back(vert);
    1477             :         }
    1478             : }
    1479             : 
    1480             : /*
    1481             :         MeshCollector - for meshnodes and converted drawtypes.
    1482             : */
    1483             : 
    1484      113667 : void MeshCollector::append(const TileSpec &tile,
    1485             :                 const video::S3DVertex *vertices, u32 numVertices,
    1486             :                 const u16 *indices, u32 numIndices,
    1487             :                 v3f pos, video::SColor c)
    1488             : {
    1489      113667 :         if (numIndices > 65535) {
    1490           0 :                 dstream<<"FIXME: MeshCollector::append() called with numIndices="<<numIndices<<" (limit 65535)"<<std::endl;
    1491           0 :                 return;
    1492             :         }
    1493             : 
    1494      113667 :         PreMeshBuffer *p = NULL;
    1495     1546681 :         for (u32 i = 0; i < prebuffers.size(); i++) {
    1496     1538872 :                 PreMeshBuffer &pp = prebuffers[i];
    1497     1538872 :                 if(pp.tile != tile)
    1498     1433014 :                         continue;
    1499      105858 :                 if(pp.indices.size() + numIndices > 65535)
    1500           0 :                         continue;
    1501             : 
    1502      105858 :                 p = &pp;
    1503      105858 :                 break;
    1504             :         }
    1505             : 
    1506      113667 :         if (p == NULL) {
    1507       15618 :                 PreMeshBuffer pp;
    1508        7809 :                 pp.tile = tile;
    1509        7809 :                 prebuffers.push_back(pp);
    1510        7809 :                 p = &prebuffers[prebuffers.size() - 1];
    1511             :         }
    1512             : 
    1513      113667 :         u32 vertex_count = p->vertices.size();
    1514     3391725 :         for (u32 i = 0; i < numIndices; i++) {
    1515     3278058 :                 u32 j = indices[i] + vertex_count;
    1516     3278058 :                 p->indices.push_back(j);
    1517             :         }
    1518             : 
    1519     1546550 :         for (u32 i = 0; i < numVertices; i++) {
    1520     4298649 :                 video::S3DVertexTangents vert(vertices[i].Pos + pos, vertices[i].Normal,
    1521     5731532 :                         c, vertices[i].TCoords);
    1522     1432883 :                 p->vertices.push_back(vert);
    1523             :         }
    1524           3 : }

Generated by: LCOV version 1.11