LCOV - code coverage report
Current view: top level - src - voxel.cpp (source / functions) Hit Total Coverage
Test: report Lines: 53 202 26.2 %
Date: 2015-07-11 18:23:49 Functions: 7 15 46.7 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 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 "voxel.h"
      21             : #include "map.h"
      22             : #include "gettime.h"
      23             : #include "nodedef.h"
      24             : #include "util/timetaker.h"
      25             : #include <string.h>  // memcpy, memset
      26             : 
      27             : /*
      28             :         Debug stuff
      29             : */
      30             : u32 addarea_time = 0;
      31             : u32 emerge_time = 0;
      32             : u32 emerge_load_time = 0;
      33             : u32 clearflag_time = 0;
      34             : //u32 getwaterpressure_time = 0;
      35             : //u32 spreadwaterpressure_time = 0;
      36             : u32 updateareawaterpressure_time = 0;
      37             : u32 flowwater_pre_time = 0;
      38             : 
      39             : 
      40        3549 : VoxelManipulator::VoxelManipulator():
      41             :         m_data(NULL),
      42        3549 :         m_flags(NULL)
      43             : {
      44        3549 : }
      45             : 
      46        7098 : VoxelManipulator::~VoxelManipulator()
      47             : {
      48        3549 :         clear();
      49        3549 : }
      50             : 
      51        7098 : void VoxelManipulator::clear()
      52             : {
      53             :         // Reset area to volume=0
      54        7098 :         m_area = VoxelArea();
      55        7098 :         delete[] m_data;
      56        7098 :         m_data = NULL;
      57        7098 :         delete[] m_flags;
      58        7098 :         m_flags = NULL;
      59        7098 : }
      60             : 
      61           0 : void VoxelManipulator::print(std::ostream &o, INodeDefManager *ndef,
      62             :                 VoxelPrintMode mode)
      63             : {
      64           0 :         v3s16 em = m_area.getExtent();
      65           0 :         v3s16 of = m_area.MinEdge;
      66           0 :         o<<"size: "<<em.X<<"x"<<em.Y<<"x"<<em.Z
      67           0 :          <<" offset: ("<<of.X<<","<<of.Y<<","<<of.Z<<")"<<std::endl;
      68             : 
      69           0 :         for(s32 y=m_area.MaxEdge.Y; y>=m_area.MinEdge.Y; y--)
      70             :         {
      71           0 :                 if(em.X >= 3 && em.Y >= 3)
      72             :                 {
      73           0 :                         if     (y==m_area.MinEdge.Y+2) o<<"^     ";
      74           0 :                         else if(y==m_area.MinEdge.Y+1) o<<"|     ";
      75           0 :                         else if(y==m_area.MinEdge.Y+0) o<<"y x-> ";
      76           0 :                         else                           o<<"      ";
      77             :                 }
      78             : 
      79           0 :                 for(s32 z=m_area.MinEdge.Z; z<=m_area.MaxEdge.Z; z++)
      80             :                 {
      81           0 :                         for(s32 x=m_area.MinEdge.X; x<=m_area.MaxEdge.X; x++)
      82             :                         {
      83           0 :                                 u8 f = m_flags[m_area.index(x,y,z)];
      84             :                                 char c;
      85           0 :                                 if(f & VOXELFLAG_NO_DATA)
      86           0 :                                         c = 'N';
      87             :                                 else
      88             :                                 {
      89           0 :                                         c = 'X';
      90           0 :                                         MapNode n = m_data[m_area.index(x,y,z)];
      91           0 :                                         content_t m = n.getContent();
      92           0 :                                         u8 pr = n.param2;
      93           0 :                                         if(mode == VOXELPRINT_MATERIAL)
      94             :                                         {
      95           0 :                                                 if(m <= 9)
      96           0 :                                                         c = m + '0';
      97             :                                         }
      98           0 :                                         else if(mode == VOXELPRINT_WATERPRESSURE)
      99             :                                         {
     100           0 :                                                 if(ndef->get(m).isLiquid())
     101             :                                                 {
     102           0 :                                                         c = 'w';
     103           0 :                                                         if(pr <= 9)
     104           0 :                                                                 c = pr + '0';
     105             :                                                 }
     106           0 :                                                 else if(m == CONTENT_AIR)
     107             :                                                 {
     108           0 :                                                         c = ' ';
     109             :                                                 }
     110             :                                                 else
     111             :                                                 {
     112           0 :                                                         c = '#';
     113             :                                                 }
     114             :                                         }
     115           0 :                                         else if(mode == VOXELPRINT_LIGHT_DAY)
     116             :                                         {
     117           0 :                                                 if(ndef->get(m).light_source != 0)
     118           0 :                                                         c = 'S';
     119           0 :                                                 else if(ndef->get(m).light_propagates == false)
     120           0 :                                                         c = 'X';
     121             :                                                 else
     122             :                                                 {
     123           0 :                                                         u8 light = n.getLight(LIGHTBANK_DAY, ndef);
     124           0 :                                                         if(light < 10)
     125           0 :                                                                 c = '0' + light;
     126             :                                                         else
     127           0 :                                                                 c = 'a' + (light-10);
     128             :                                                 }
     129             :                                         }
     130             :                                 }
     131           0 :                                 o<<c;
     132             :                         }
     133           0 :                         o<<' ';
     134             :                 }
     135           0 :                 o<<std::endl;
     136             :         }
     137           0 : }
     138             : 
     139    17914543 : void VoxelManipulator::addArea(const VoxelArea &area)
     140             : {
     141             :         // Cancel if requested area has zero volume
     142    17914543 :         if (area.hasEmptyExtent())
     143    17911023 :                 return;
     144             : 
     145             :         // Cancel if m_area already contains the requested area
     146    17914482 :         if(m_area.contains(area))
     147    17911023 :                 return;
     148             : 
     149        7098 :         TimeTaker timer("addArea", &addarea_time);
     150             : 
     151             :         // Calculate new area
     152        3549 :         VoxelArea new_area;
     153             :         // New area is the requested area if m_area has zero volume
     154        3549 :         if(m_area.hasEmptyExtent())
     155             :         {
     156        3549 :                 new_area = area;
     157             :         }
     158             :         // Else add requested area to m_area
     159             :         else
     160             :         {
     161           0 :                 new_area = m_area;
     162           0 :                 new_area.addArea(area);
     163             :         }
     164             : 
     165        3549 :         s32 new_size = new_area.getVolume();
     166             : 
     167             :         /*dstream<<"adding area ";
     168             :         area.print(dstream);
     169             :         dstream<<", old area ";
     170             :         m_area.print(dstream);
     171             :         dstream<<", new area ";
     172             :         new_area.print(dstream);
     173             :         dstream<<", new_size="<<new_size;
     174             :         dstream<<std::endl;*/
     175             : 
     176             :         // Allocate new data and clear flags
     177        3549 :         MapNode *new_data = new MapNode[new_size];
     178             :         assert(new_data);
     179        3549 :         u8 *new_flags = new u8[new_size];
     180             :         assert(new_flags);
     181        3549 :         memset(new_flags, VOXELFLAG_NO_DATA, new_size);
     182             : 
     183             :         // Copy old data
     184        3549 :         s32 old_x_width = m_area.MaxEdge.X - m_area.MinEdge.X + 1;
     185        3549 :         for(s32 z=m_area.MinEdge.Z; z<=m_area.MaxEdge.Z; z++)
     186           0 :         for(s32 y=m_area.MinEdge.Y; y<=m_area.MaxEdge.Y; y++)
     187             :         {
     188           0 :                 unsigned int old_index = m_area.index(m_area.MinEdge.X,y,z);
     189           0 :                 unsigned int new_index = new_area.index(m_area.MinEdge.X,y,z);
     190             : 
     191           0 :                 memcpy(&new_data[new_index], &m_data[old_index],
     192           0 :                                 old_x_width * sizeof(MapNode));
     193           0 :                 memcpy(&new_flags[new_index], &m_flags[old_index],
     194           0 :                                 old_x_width * sizeof(u8));
     195             :         }
     196             : 
     197             :         // Replace area, data and flags
     198             : 
     199        3549 :         m_area = new_area;
     200             : 
     201        3549 :         MapNode *old_data = m_data;
     202        3549 :         u8 *old_flags = m_flags;
     203             : 
     204             :         /*dstream<<"old_data="<<(int)old_data<<", new_data="<<(int)new_data
     205             :         <<", old_flags="<<(int)m_flags<<", new_flags="<<(int)new_flags<<std::endl;*/
     206             : 
     207        3549 :         m_data = new_data;
     208        3549 :         m_flags = new_flags;
     209             : 
     210        3549 :         delete[] old_data;
     211        3549 :         delete[] old_flags;
     212             : 
     213             :         //dstream<<"addArea done"<<std::endl;
     214             : }
     215             : 
     216       56321 : void VoxelManipulator::copyFrom(MapNode *src, const VoxelArea& src_area,
     217             :                 v3s16 from_pos, v3s16 to_pos, v3s16 size)
     218             : {
     219             :         /* The reason for this optimised code is that we're a member function
     220             :          * and the data type/layout of m_data is know to us: it's stored as
     221             :          * [z*h*w + y*h + x]. Therefore we can take the calls to m_area index
     222             :          * (which performs the preceding mapping/indexing of m_data) out of the
     223             :          * inner loop and calculate the next index as we're iterating to gain
     224             :          * performance.
     225             :          *
     226             :          * src_step and dest_step is the amount required to be added to our index
     227             :          * every time y increments. Because the destination area may be larger
     228             :          * than the source area we need one additional variable (otherwise we could
     229             :          * just continue adding dest_step as is done for the source data): dest_mod.
     230             :          * dest_mod is the difference in size between a "row" in the source data
     231             :          * and a "row" in the destination data (I am using the term row loosely
     232             :          * and for illustrative purposes). E.g.
     233             :          *
     234             :          * src       <-------------------->|'''''' dest mod ''''''''
     235             :          * dest      <--------------------------------------------->
     236             :          *
     237             :          * dest_mod (it's essentially a modulus) is added to the destination index
     238             :          * after every full iteration of the y span.
     239             :          *
     240             :          * This method falls under the category "linear array and incrementing
     241             :          * index".
     242             :          */
     243             : 
     244       56321 :         s32 src_step = src_area.getExtent().X;
     245       56321 :         s32 dest_step = m_area.getExtent().X;
     246       56321 :         s32 dest_mod = m_area.index(to_pos.X, to_pos.Y, to_pos.Z + 1)
     247       56321 :                         - m_area.index(to_pos.X, to_pos.Y, to_pos.Z)
     248       56321 :                         - dest_step * size.Y;
     249             : 
     250       56321 :         s32 i_src = src_area.index(from_pos.X, from_pos.Y, from_pos.Z);
     251       56321 :         s32 i_local = m_area.index(to_pos.X, to_pos.Y, to_pos.Z);
     252             : 
     253      957489 :         for (s16 z = 0; z < size.Z; z++) {
     254    15321392 :                 for (s16 y = 0; y < size.Y; y++) {
     255    14420224 :                         memcpy(&m_data[i_local], &src[i_src], size.X * sizeof(*m_data));
     256    14420224 :                         memset(&m_flags[i_local], 0, size.X);
     257    14420224 :                         i_src += src_step;
     258    14420224 :                         i_local += dest_step;
     259             :                 }
     260      901168 :                 i_local += dest_mod;
     261             :         }
     262       56321 : }
     263             : 
     264           0 : void VoxelManipulator::copyTo(MapNode *dst, const VoxelArea& dst_area,
     265             :                 v3s16 dst_pos, v3s16 from_pos, v3s16 size)
     266             : {
     267           0 :         for(s16 z=0; z<size.Z; z++)
     268           0 :         for(s16 y=0; y<size.Y; y++)
     269             :         {
     270           0 :                 s32 i_dst = dst_area.index(dst_pos.X, dst_pos.Y+y, dst_pos.Z+z);
     271           0 :                 s32 i_local = m_area.index(from_pos.X, from_pos.Y+y, from_pos.Z+z);
     272           0 :                 for (s16 x = 0; x < size.X; x++) {
     273           0 :                         if (m_data[i_local].getContent() != CONTENT_IGNORE)
     274           0 :                                 dst[i_dst] = m_data[i_local];
     275           0 :                         i_dst++;
     276           0 :                         i_local++;
     277             :                 }
     278             :         }
     279           0 : }
     280             : 
     281             : /*
     282             :         Algorithms
     283             :         -----------------------------------------------------
     284             : */
     285             : 
     286           0 : void VoxelManipulator::clearFlag(u8 flags)
     287             : {
     288             :         // 0-1ms on moderate area
     289           0 :         TimeTaker timer("clearFlag", &clearflag_time);
     290             : 
     291             :         //v3s16 s = m_area.getExtent();
     292             : 
     293             :         /*dstream<<"clearFlag clearing area of size "
     294             :                         <<""<<s.X<<"x"<<s.Y<<"x"<<s.Z<<""
     295             :                         <<std::endl;*/
     296             : 
     297             :         //s32 count = 0;
     298             : 
     299             :         /*for(s32 z=m_area.MinEdge.Z; z<=m_area.MaxEdge.Z; z++)
     300             :         for(s32 y=m_area.MinEdge.Y; y<=m_area.MaxEdge.Y; y++)
     301             :         for(s32 x=m_area.MinEdge.X; x<=m_area.MaxEdge.X; x++)
     302             :         {
     303             :                 u8 f = m_flags[m_area.index(x,y,z)];
     304             :                 m_flags[m_area.index(x,y,z)] &= ~flags;
     305             :                 if(m_flags[m_area.index(x,y,z)] != f)
     306             :                         count++;
     307             :         }*/
     308             : 
     309           0 :         s32 volume = m_area.getVolume();
     310           0 :         for(s32 i=0; i<volume; i++)
     311             :         {
     312           0 :                 m_flags[i] &= ~flags;
     313             :         }
     314             : 
     315             :         /*s32 volume = m_area.getVolume();
     316             :         for(s32 i=0; i<volume; i++)
     317             :         {
     318             :                 u8 f = m_flags[i];
     319             :                 m_flags[i] &= ~flags;
     320             :                 if(m_flags[i] != f)
     321             :                         count++;
     322             :         }
     323             : 
     324             :         dstream<<"clearFlag changed "<<count<<" flags out of "
     325             :                         <<volume<<" nodes"<<std::endl;*/
     326           0 : }
     327             : 
     328           0 : void VoxelManipulator::unspreadLight(enum LightBank bank, v3s16 p, u8 oldlight,
     329             :                 std::set<v3s16> & light_sources, INodeDefManager *nodemgr)
     330             : {
     331             :         v3s16 dirs[6] = {
     332             :                 v3s16(0,0,1), // back
     333             :                 v3s16(0,1,0), // top
     334             :                 v3s16(1,0,0), // right
     335             :                 v3s16(0,0,-1), // front
     336             :                 v3s16(0,-1,0), // bottom
     337             :                 v3s16(-1,0,0), // left
     338           0 :         };
     339             : 
     340           0 :         VoxelArea voxel_area(p - v3s16(1,1,1), p + v3s16(1,1,1));
     341           0 :         addArea(voxel_area);
     342             : 
     343             :         // Loop through 6 neighbors
     344           0 :         for(u16 i=0; i<6; i++)
     345             :         {
     346             :                 // Get the position of the neighbor node
     347           0 :                 v3s16 n2pos = p + dirs[i];
     348             : 
     349           0 :                 u32 n2i = m_area.index(n2pos);
     350             : 
     351           0 :                 if(m_flags[n2i] & VOXELFLAG_NO_DATA)
     352           0 :                         continue;
     353             : 
     354           0 :                 MapNode &n2 = m_data[n2i];
     355             : 
     356             :                 /*
     357             :                         If the neighbor is dimmer than what was specified
     358             :                         as oldlight (the light of the previous node)
     359             :                 */
     360           0 :                 u8 light2 = n2.getLight(bank, nodemgr);
     361           0 :                 if(light2 < oldlight)
     362             :                 {
     363             :                         /*
     364             :                                 And the neighbor is transparent and it has some light
     365             :                         */
     366           0 :                         if(nodemgr->get(n2).light_propagates && light2 != 0)
     367             :                         {
     368             :                                 /*
     369             :                                         Set light to 0 and add to queue
     370             :                                 */
     371             : 
     372           0 :                                 n2.setLight(bank, 0, nodemgr);
     373             : 
     374           0 :                                 unspreadLight(bank, n2pos, light2, light_sources, nodemgr);
     375             : 
     376             :                                 /*
     377             :                                         Remove from light_sources if it is there
     378             :                                         NOTE: This doesn't happen nearly at all
     379             :                                 */
     380             :                                 /*if(light_sources.find(n2pos))
     381             :                                 {
     382             :                                         std::cout<<"Removed from light_sources"<<std::endl;
     383             :                                         light_sources.remove(n2pos);
     384             :                                 }*/
     385             :                         }
     386             :                 }
     387             :                 else{
     388           0 :                         light_sources.insert(n2pos);
     389             :                 }
     390             :         }
     391           0 : }
     392             : 
     393             : #if 1
     394             : /*
     395             :         Goes recursively through the neighbours of the node.
     396             : 
     397             :         Alters only transparent nodes.
     398             : 
     399             :         If the lighting of the neighbour is lower than the lighting of
     400             :         the node was (before changing it to 0 at the step before), the
     401             :         lighting of the neighbour is set to 0 and then the same stuff
     402             :         repeats for the neighbour.
     403             : 
     404             :         The ending nodes of the routine are stored in light_sources.
     405             :         This is useful when a light is removed. In such case, this
     406             :         routine can be called for the light node and then again for
     407             :         light_sources to re-light the area without the removed light.
     408             : 
     409             :         values of from_nodes are lighting values.
     410             : */
     411           0 : void VoxelManipulator::unspreadLight(enum LightBank bank,
     412             :                 std::map<v3s16, u8> & from_nodes,
     413             :                 std::set<v3s16> & light_sources, INodeDefManager *nodemgr)
     414             : {
     415           0 :         if(from_nodes.empty())
     416           0 :                 return;
     417             : 
     418           0 :         for(std::map<v3s16, u8>::iterator j = from_nodes.begin();
     419           0 :                 j != from_nodes.end(); ++j)
     420             :         {
     421           0 :                 unspreadLight(bank, j->first, j->second, light_sources, nodemgr);
     422             :         }
     423             : }
     424             : #endif
     425             : 
     426             : #if 0
     427             : /*
     428             :         Goes recursively through the neighbours of the node.
     429             : 
     430             :         Alters only transparent nodes.
     431             : 
     432             :         If the lighting of the neighbour is lower than the lighting of
     433             :         the node was (before changing it to 0 at the step before), the
     434             :         lighting of the neighbour is set to 0 and then the same stuff
     435             :         repeats for the neighbour.
     436             : 
     437             :         The ending nodes of the routine are stored in light_sources.
     438             :         This is useful when a light is removed. In such case, this
     439             :         routine can be called for the light node and then again for
     440             :         light_sources to re-light the area without the removed light.
     441             : 
     442             :         values of from_nodes are lighting values.
     443             : */
     444             : void VoxelManipulator::unspreadLight(enum LightBank bank,
     445             :                 core::map<v3s16, u8> & from_nodes,
     446             :                 core::map<v3s16, bool> & light_sources)
     447             : {
     448             :         v3s16 dirs[6] = {
     449             :                 v3s16(0,0,1), // back
     450             :                 v3s16(0,1,0), // top
     451             :                 v3s16(1,0,0), // right
     452             :                 v3s16(0,0,-1), // front
     453             :                 v3s16(0,-1,0), // bottom
     454             :                 v3s16(-1,0,0), // left
     455             :         };
     456             : 
     457             :         if(from_nodes.size() == 0)
     458             :                 return;
     459             : 
     460             :         core::map<v3s16, u8> unlighted_nodes;
     461             :         core::map<v3s16, u8>::Iterator j;
     462             :         j = from_nodes.getIterator();
     463             : 
     464             :         for(; j.atEnd() == false; j++)
     465             :         {
     466             :                 v3s16 pos = j.getNode()->getKey();
     467             : 
     468             :                 addArea(VoxelArea(pos - v3s16(1,1,1), pos + v3s16(1,1,1)));
     469             : 
     470             :                 //MapNode &n = m_data[m_area.index(pos)];
     471             : 
     472             :                 u8 oldlight = j.getNode()->getValue();
     473             : 
     474             :                 // Loop through 6 neighbors
     475             :                 for(u16 i=0; i<6; i++)
     476             :                 {
     477             :                         // Get the position of the neighbor node
     478             :                         v3s16 n2pos = pos + dirs[i];
     479             : 
     480             :                         u32 n2i = m_area.index(n2pos);
     481             : 
     482             :                         if(m_flags[n2i] & VOXELFLAG_NO_DATA)
     483             :                                 continue;
     484             : 
     485             :                         MapNode &n2 = m_data[n2i];
     486             : 
     487             :                         /*
     488             :                                 If the neighbor is dimmer than what was specified
     489             :                                 as oldlight (the light of the previous node)
     490             :                         */
     491             :                         if(n2.getLight(bank, nodemgr) < oldlight)
     492             :                         {
     493             :                                 /*
     494             :                                         And the neighbor is transparent and it has some light
     495             :                                 */
     496             :                                 if(nodemgr->get(n2).light_propagates && n2.getLight(bank, nodemgr) != 0)
     497             :                                 {
     498             :                                         /*
     499             :                                                 Set light to 0 and add to queue
     500             :                                         */
     501             : 
     502             :                                         u8 current_light = n2.getLight(bank, nodemgr);
     503             :                                         n2.setLight(bank, 0);
     504             : 
     505             :                                         unlighted_nodes.insert(n2pos, current_light);
     506             : 
     507             :                                         /*
     508             :                                                 Remove from light_sources if it is there
     509             :                                                 NOTE: This doesn't happen nearly at all
     510             :                                         */
     511             :                                         /*if(light_sources.find(n2pos))
     512             :                                         {
     513             :                                                 std::cout<<"Removed from light_sources"<<std::endl;
     514             :                                                 light_sources.remove(n2pos);
     515             :                                         }*/
     516             :                                 }
     517             :                         }
     518             :                         else{
     519             :                                 light_sources.insert(n2pos, true);
     520             :                         }
     521             :                 }
     522             :         }
     523             : 
     524             :         /*dstream<<"unspreadLight(): Changed block "
     525             :                         <<blockchangecount<<" times"
     526             :                         <<" for "<<from_nodes.size()<<" nodes"
     527             :                         <<std::endl;*/
     528             : 
     529             :         if(unlighted_nodes.size() > 0)
     530             :                 unspreadLight(bank, unlighted_nodes, light_sources);
     531             : }
     532             : #endif
     533             : 
     534           0 : void VoxelManipulator::spreadLight(enum LightBank bank, v3s16 p,
     535             :                 INodeDefManager *nodemgr)
     536             : {
     537             :         const v3s16 dirs[6] = {
     538             :                 v3s16(0,0,1), // back
     539             :                 v3s16(0,1,0), // top
     540             :                 v3s16(1,0,0), // right
     541             :                 v3s16(0,0,-1), // front
     542             :                 v3s16(0,-1,0), // bottom
     543             :                 v3s16(-1,0,0), // left
     544           0 :         };
     545             : 
     546           0 :         VoxelArea voxel_area(p - v3s16(1,1,1), p + v3s16(1,1,1));
     547           0 :         addArea(voxel_area);
     548             : 
     549           0 :         u32 i = m_area.index(p);
     550             : 
     551           0 :         if(m_flags[i] & VOXELFLAG_NO_DATA)
     552           0 :                 return;
     553             : 
     554           0 :         MapNode &n = m_data[i];
     555             : 
     556           0 :         u8 oldlight = n.getLight(bank, nodemgr);
     557           0 :         u8 newlight = diminish_light(oldlight);
     558             : 
     559             :         // Loop through 6 neighbors
     560           0 :         for(u16 i=0; i<6; i++)
     561             :         {
     562             :                 // Get the position of the neighbor node
     563           0 :                 v3s16 n2pos = p + dirs[i];
     564             : 
     565           0 :                 u32 n2i = m_area.index(n2pos);
     566             : 
     567           0 :                 if(m_flags[n2i] & VOXELFLAG_NO_DATA)
     568           0 :                         continue;
     569             : 
     570           0 :                 MapNode &n2 = m_data[n2i];
     571             : 
     572           0 :                 u8 light2 = n2.getLight(bank, nodemgr);
     573             : 
     574             :                 /*
     575             :                         If the neighbor is brighter than the current node,
     576             :                         add to list (it will light up this node on its turn)
     577             :                 */
     578           0 :                 if(light2 > undiminish_light(oldlight))
     579             :                 {
     580           0 :                         spreadLight(bank, n2pos, nodemgr);
     581             :                 }
     582             :                 /*
     583             :                         If the neighbor is dimmer than how much light this node
     584             :                         would spread on it, add to list
     585             :                 */
     586           0 :                 if(light2 < newlight)
     587             :                 {
     588           0 :                         if(nodemgr->get(n2).light_propagates)
     589             :                         {
     590           0 :                                 n2.setLight(bank, newlight, nodemgr);
     591           0 :                                 spreadLight(bank, n2pos, nodemgr);
     592             :                         }
     593             :                 }
     594             :         }
     595             : }
     596             : 
     597             : #if 0
     598             : /*
     599             :         Lights neighbors of from_nodes, collects all them and then
     600             :         goes on recursively.
     601             : 
     602             :         NOTE: This is faster on small areas but will overflow the
     603             :               stack on large areas. Thus it is not used.
     604             : */
     605             : void VoxelManipulator::spreadLight(enum LightBank bank,
     606             :                 core::map<v3s16, bool> & from_nodes)
     607             : {
     608             :         if(from_nodes.size() == 0)
     609             :                 return;
     610             : 
     611             :         core::map<v3s16, bool> lighted_nodes;
     612             :         core::map<v3s16, bool>::Iterator j;
     613             :         j = from_nodes.getIterator();
     614             : 
     615             :         for(; j.atEnd() == false; j++)
     616             :         {
     617             :                 v3s16 pos = j.getNode()->getKey();
     618             : 
     619             :                 spreadLight(bank, pos);
     620             :         }
     621             : }
     622             : #endif
     623             : 
     624           1 : const MapNode VoxelManipulator::ContentIgnoreNode = MapNode(CONTENT_IGNORE);
     625             : 
     626             : #if 1
     627             : /*
     628             :         Lights neighbors of from_nodes, collects all them and then
     629             :         goes on recursively.
     630             : */
     631           0 : void VoxelManipulator::spreadLight(enum LightBank bank,
     632             :                 std::set<v3s16> & from_nodes, INodeDefManager *nodemgr)
     633             : {
     634             :         const v3s16 dirs[6] = {
     635             :                 v3s16(0,0,1), // back
     636             :                 v3s16(0,1,0), // top
     637             :                 v3s16(1,0,0), // right
     638             :                 v3s16(0,0,-1), // front
     639             :                 v3s16(0,-1,0), // bottom
     640             :                 v3s16(-1,0,0), // left
     641           0 :         };
     642             : 
     643           0 :         if(from_nodes.empty())
     644           0 :                 return;
     645             : 
     646           0 :         std::set<v3s16> lighted_nodes;
     647             : 
     648           0 :         for(std::set<v3s16>::iterator j = from_nodes.begin();
     649           0 :                 j != from_nodes.end(); ++j)
     650             :         {
     651           0 :                 v3s16 pos = *j;
     652             : 
     653           0 :                 VoxelArea voxel_area(pos - v3s16(1,1,1), pos + v3s16(1,1,1));
     654           0 :                 addArea(voxel_area);
     655             : 
     656           0 :                 u32 i = m_area.index(pos);
     657             : 
     658           0 :                 if(m_flags[i] & VOXELFLAG_NO_DATA)
     659           0 :                         continue;
     660             : 
     661           0 :                 MapNode &n = m_data[i];
     662             : 
     663           0 :                 u8 oldlight = n.getLight(bank, nodemgr);
     664           0 :                 u8 newlight = diminish_light(oldlight);
     665             : 
     666             :                 // Loop through 6 neighbors
     667           0 :                 for(u16 i=0; i<6; i++)
     668             :                 {
     669             :                         // Get the position of the neighbor node
     670           0 :                         v3s16 n2pos = pos + dirs[i];
     671             : 
     672             :                         try
     673             :                         {
     674           0 :                                 u32 n2i = m_area.index(n2pos);
     675             : 
     676           0 :                                 if(m_flags[n2i] & VOXELFLAG_NO_DATA)
     677           0 :                                         continue;
     678             : 
     679           0 :                                 MapNode &n2 = m_data[n2i];
     680             : 
     681           0 :                                 u8 light2 = n2.getLight(bank, nodemgr);
     682             : 
     683             :                                 /*
     684             :                                         If the neighbor is brighter than the current node,
     685             :                                         add to list (it will light up this node on its turn)
     686             :                                 */
     687           0 :                                 if(light2 > undiminish_light(oldlight))
     688             :                                 {
     689           0 :                                         lighted_nodes.insert(n2pos);
     690             :                                 }
     691             :                                 /*
     692             :                                         If the neighbor is dimmer than how much light this node
     693             :                                         would spread on it, add to list
     694             :                                 */
     695           0 :                                 if(light2 < newlight)
     696             :                                 {
     697           0 :                                         if(nodemgr->get(n2).light_propagates)
     698             :                                         {
     699           0 :                                                 n2.setLight(bank, newlight, nodemgr);
     700           0 :                                                 lighted_nodes.insert(n2pos);
     701             :                                         }
     702             :                                 }
     703             :                         }
     704           0 :                         catch(InvalidPositionException &e)
     705             :                         {
     706           0 :                                 continue;
     707             :                         }
     708             :                 }
     709             :         }
     710             : 
     711             :         /*dstream<<"spreadLight(): Changed block "
     712             :                         <<blockchangecount<<" times"
     713             :                         <<" for "<<from_nodes.size()<<" nodes"
     714             :                         <<std::endl;*/
     715             : 
     716           0 :         if(!lighted_nodes.empty())
     717           0 :                 spreadLight(bank, lighted_nodes, nodemgr);
     718           3 : }
     719             : #endif
     720             : 
     721             : //END

Generated by: LCOV version 1.11