summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-01-24 16:36:58 +0200
committerPerttu Ahola <celeron55@gmail.com>2011-01-24 16:36:58 +0200
commit3909e712a012c11793effc408fd348e438a9ac5b (patch)
tree237daebc0dd1e7053af50962d01d05a5630cff8e
parent87554408ca667bfb86a6472d4835a893e457c0ba (diff)
downloadminetest-3909e712a012c11793effc408fd348e438a9ac5b.tar.gz
minetest-3909e712a012c11793effc408fd348e438a9ac5b.tar.bz2
minetest-3909e712a012c11793effc408fd348e438a9ac5b.zip
Faster lighting at map generation time
-rw-r--r--src/defaultsettings.cpp1
-rw-r--r--src/main.cpp3
-rw-r--r--src/map.cpp141
-rw-r--r--src/map.h15
-rw-r--r--src/player.cpp5
-rw-r--r--src/server.cpp66
-rw-r--r--src/voxel.cpp389
-rw-r--r--src/voxel.h18
8 files changed, 605 insertions, 33 deletions
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 6cd242f01..4046b81b9 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -47,6 +47,7 @@ void set_default_settings()
g_settings.setDefault("objectdata_interval", "0.2");
g_settings.setDefault("active_object_range", "2");
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
+ //g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
g_settings.setDefault("max_block_send_distance", "6");
g_settings.setDefault("max_block_generate_distance", "6");
diff --git a/src/main.cpp b/src/main.cpp
index 092d62988..d2f8a6b9d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -259,7 +259,8 @@ TODO: Remove HMParams
TODO: Flowing water to actually contain flow direction information
-TODO: Faster lighting using VoxelManipulator
+TODO: Remove duplicate lighting implementation from Map (leave
+ VoxelManipulator)
Doing now:
----------
diff --git a/src/map.cpp b/src/map.cpp
index 09fb154aa..bbcc0f36f 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -622,10 +622,13 @@ void Map::updateLighting(enum LightBank bank,
core::map<v3s16, MapBlock*> & modified_blocks)
{
/*m_dout<<DTIME<<"Map::updateLighting(): "
- <<a_blocks.getSize()<<" blocks... ";*/
+ <<a_blocks.size()<<" blocks."<<std::endl;*/
+
+ //TimeTaker timer("updateLighting");
// For debugging
- bool debug=false;
+ bool debug=true;
+
u32 count_was = modified_blocks.size();
core::map<v3s16, bool> light_sources;
@@ -720,9 +723,10 @@ void Map::updateLighting(enum LightBank bank,
}
}
-
+
+#if 0
{
- //TimeTaker timer("unspreadLight");
+ TimeTaker timer("unspreadLight");
unspreadLight(bank, unlight_from, light_sources, modified_blocks);
}
@@ -741,7 +745,7 @@ void Map::updateLighting(enum LightBank bank,
// - Find out why it works
{
- //TimeTaker timer("spreadLight");
+ TimeTaker timer("spreadLight");
spreadLight(bank, light_sources, modified_blocks);
}
@@ -751,6 +755,36 @@ void Map::updateLighting(enum LightBank bank,
count_was = modified_blocks.size();
dstream<<"spreadLight modified "<<diff<<std::endl;
}
+#endif
+
+ {
+ //MapVoxelManipulator vmanip(this);
+
+ ManualMapVoxelManipulator vmanip(this);
+
+ core::map<v3s16, MapBlock*>::Iterator i;
+ i = a_blocks.getIterator();
+ for(; i.atEnd() == false; i++)
+ {
+ MapBlock *block = i.getNode()->getValue();
+ v3s16 p = block->getPos();
+ vmanip.initialEmerge(p - v3s16(1,1,1), p + v3s16(1,1,1));
+ }
+ {
+ //TimeTaker timer("unSpreadLight");
+ vmanip.unspreadLight(bank, unlight_from, light_sources);
+ }
+ {
+ //TimeTaker timer("spreadLight");
+ vmanip.spreadLight(bank, light_sources);
+ }
+ {
+ //TimeTaker timer("blitBack");
+ vmanip.blitBack(modified_blocks);
+ }
+ /*dstream<<"emerge_time="<<emerge_time<<std::endl;
+ emerge_time = 0;*/
+ }
//m_dout<<"Done ("<<getTimestamp()<<")"<<std::endl;
}
@@ -2220,7 +2254,8 @@ MapBlock * ServerMap::emergeBlock(
}
//dstream<<"Not found on disk, generating."<<std::endl;
- //TimeTaker("emergeBlock()", g_irrlicht);
+ // 0ms
+ //TimeTaker("emergeBlock() generate");
/*
Do not generate over-limit
@@ -4138,7 +4173,10 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
#endif
#if 0
-void MapVoxelManipulator::emerge(VoxelArea a)
+/*
+ NOTE: This is slow
+*/
+void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
{
TimeTaker timer1("emerge", &emerge_time);
@@ -4185,6 +4223,9 @@ void MapVoxelManipulator::blitBack
return;
//TimeTaker timer1("blitBack");
+
+ /*dstream<<"blitBack(): m_loaded_blocks.size()="
+ <<m_loaded_blocks.size()<<std::endl;*/
/*
Initialize block cache
@@ -4241,4 +4282,90 @@ void MapVoxelManipulator::blitBack
}
}
+ManualMapVoxelManipulator::ManualMapVoxelManipulator(Map *map):
+ MapVoxelManipulator(map)
+{
+}
+
+ManualMapVoxelManipulator::~ManualMapVoxelManipulator()
+{
+}
+
+void ManualMapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
+{
+ // Just create the area to avoid segfaults
+ VoxelManipulator::emerge(a, caller_id);
+
+ /*
+ Just create the area to avoid segfaults
+ */
+ /*addArea(a);
+ for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
+ for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
+ for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++)
+ {
+ s32 i = m_area.index(x,y,z);
+ // Don't touch nodes that have already been loaded
+ if(!(m_flags[i] & VOXELFLAG_NOT_LOADED))
+ continue;
+ m_flags[i] = VOXELFLAG_INEXISTENT;
+ }*/
+}
+
+void ManualMapVoxelManipulator::initialEmerge(
+ v3s16 blockpos_min, v3s16 blockpos_max)
+{
+ TimeTaker timer1("emerge", &emerge_time);
+
+ // Units of these are MapBlocks
+ v3s16 p_min = blockpos_min;
+ v3s16 p_max = blockpos_max;
+
+ VoxelArea block_area_nodes
+ (p_min*MAP_BLOCKSIZE, (p_max+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
+
+ addArea(block_area_nodes);
+
+ for(s32 z=p_min.Z; z<=p_max.Z; z++)
+ for(s32 y=p_min.Y; y<=p_max.Y; y++)
+ for(s32 x=p_min.X; x<=p_max.X; x++)
+ {
+ v3s16 p(x,y,z);
+ core::map<v3s16, bool>::Node *n;
+ n = m_loaded_blocks.find(p);
+ if(n != NULL)
+ continue;
+
+ bool block_data_inexistent = false;
+ try
+ {
+ TimeTaker timer1("emerge load", &emerge_load_time);
+
+ MapBlock *block = m_map->getBlockNoCreate(p);
+ if(block->isDummy())
+ block_data_inexistent = true;
+ else
+ block->copyTo(*this);
+ }
+ catch(InvalidPositionException &e)
+ {
+ block_data_inexistent = true;
+ }
+
+ if(block_data_inexistent)
+ {
+ VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
+ // Fill with VOXELFLAG_INEXISTENT
+ for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
+ for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
+ {
+ s32 i = m_area.index(a.MinEdge.X,y,z);
+ memset(&m_flags[i], VOXELFLAG_INEXISTENT, MAP_BLOCKSIZE);
+ }
+ }
+
+ m_loaded_blocks.insert(p, true);
+ }
+}
+
//END
diff --git a/src/map.h b/src/map.h
index 3b6b169e5..787e1240f 100644
--- a/src/map.h
+++ b/src/map.h
@@ -523,7 +523,7 @@ public:
void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
-private:
+protected:
Map *m_map;
/*
NOTE: This might be used or not
@@ -534,5 +534,18 @@ private:
core::map<v3s16, bool> m_loaded_blocks;
};
+class ManualMapVoxelManipulator : public MapVoxelManipulator
+{
+public:
+ ManualMapVoxelManipulator(Map *map);
+ virtual ~ManualMapVoxelManipulator();
+
+ virtual void emerge(VoxelArea a, s32 caller_id=-1);
+
+ void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
+
+protected:
+};
+
#endif
diff --git a/src/player.cpp b/src/player.cpp
index bb25015b5..8aabb030c 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -412,8 +412,9 @@ void LocalPlayer::applyControl(float dtime)
}
else
{
- speed += move_direction;
- superspeed = true;
+ // "Turbo button"
+ /*speed += move_direction;
+ superspeed = true;*/
}
}
diff --git a/src/server.cpp b/src/server.cpp
index 65e390345..716ff77c6 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -168,7 +168,7 @@ void * EmergeThread::Thread()
changed_blocks,
lighting_invalidated_blocks);
-#if 0
+#if 1
/*
EXPERIMENTAL: Create a few other blocks too
*/
@@ -184,6 +184,19 @@ void * EmergeThread::Thread()
only_from_disk,
changed_blocks,
lighting_invalidated_blocks);
+#if 0
+ map.emergeBlock(
+ p + v3s16(0,2,0),
+ only_from_disk,
+ changed_blocks,
+ lighting_invalidated_blocks);
+
+ map.emergeBlock(
+ p + v3s16(0,-2,0),
+ only_from_disk,
+ changed_blocks,
+ lighting_invalidated_blocks);
+#endif
#endif
}
@@ -216,23 +229,6 @@ void * EmergeThread::Thread()
dout_server<<std::endl;
}
-#if 0
- /*
- Update water pressure
- */
-
- m_server->UpdateBlockWaterPressure(block, modified_blocks);
-
- for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator();
- i.atEnd() == false; i++)
- {
- MapBlock *block = i.getNode()->getValue();
- m_server->UpdateBlockWaterPressure(block, modified_blocks);
- //v3s16 p = i.getNode()->getKey();
- //m_server->UpdateBlockWaterPressure(p, modified_blocks);
- }
-#endif
-
/*
Collect a list of blocks that have been modified in
addition to the fetched one.
@@ -249,7 +245,7 @@ void * EmergeThread::Thread()
/*dstream<<"lighting "<<lighting_invalidated_blocks.size()
<<" blocks"<<std::endl;*/
- //TimeTaker timer("** updateLighting", g_device);
+ //TimeTaker timer("** updateLighting");
// Update lighting without locking the environment mutex,
// add modified blocks to changed blocks
@@ -497,7 +493,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|| p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
continue;
-
+
+ // If this is true, inexistent block will be made from scratch
bool generate = d <= d_max_gen;
if(haxmode)
@@ -514,6 +511,35 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
}
/*
+ If block is far away, don't generate it unless it is
+ near ground level
+ */
+ if(d > 4)
+ {
+ v2s16 p2d(p.X, p.Z);
+ MapSector *sector = NULL;
+ try
+ {
+ sector = server->m_env.getMap().getSectorNoGenerate(p2d);
+ }
+ catch(InvalidPositionException &e)
+ {
+ }
+
+ if(sector != NULL)
+ {
+ // Get center ground height in nodes
+ f32 gh = sector->getGroundHeight(
+ v2s16(MAP_BLOCKSIZE/2, MAP_BLOCKSIZE/2));
+ // Block center y in nodes
+ f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2);
+ // If differs a lot, don't generate
+ if(fabs(gh - y) > MAP_BLOCKSIZE*2)
+ generate = false;
+ }
+ }
+
+ /*
Don't draw if not in sight
*/
diff --git a/src/voxel.cpp b/src/voxel.cpp
index c045c949c..a0cc44d71 100644
--- a/src/voxel.cpp
+++ b/src/voxel.cpp
@@ -264,6 +264,395 @@ void VoxelManipulator::clearFlag(u8 flags)
<<volume<<" nodes"<<std::endl;*/
}
+void VoxelManipulator::unspreadLight(enum LightBank bank, v3s16 p, u8 oldlight,
+ core::map<v3s16, bool> & light_sources)
+{
+ v3s16 dirs[6] = {
+ v3s16(0,0,1), // back
+ v3s16(0,1,0), // top
+ v3s16(1,0,0), // right
+ v3s16(0,0,-1), // front
+ v3s16(0,-1,0), // bottom
+ v3s16(-1,0,0), // left
+ };
+
+ emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)));
+
+ // Loop through 6 neighbors
+ for(u16 i=0; i<6; i++)
+ {
+ // Get the position of the neighbor node
+ v3s16 n2pos = p + dirs[i];
+
+ u32 n2i = m_area.index(n2pos);
+
+ if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+ continue;
+
+ MapNode &n2 = m_data[n2i];
+
+ /*
+ If the neighbor is dimmer than what was specified
+ as oldlight (the light of the previous node)
+ */
+ if(n2.getLight(bank) < oldlight)
+ {
+ /*
+ And the neighbor is transparent and it has some light
+ */
+ if(n2.light_propagates() && n2.getLight(bank) != 0)
+ {
+ /*
+ Set light to 0 and add to queue
+ */
+
+ u8 current_light = n2.getLight(bank);
+ n2.setLight(bank, 0);
+
+ unspreadLight(bank, n2pos, current_light, light_sources);
+
+ /*
+ Remove from light_sources if it is there
+ NOTE: This doesn't happen nearly at all
+ */
+ /*if(light_sources.find(n2pos))
+ {
+ std::cout<<"Removed from light_sources"<<std::endl;
+ light_sources.remove(n2pos);
+ }*/
+ }
+ }
+ else{
+ light_sources.insert(n2pos, true);
+ }
+ }
+}
+
+#if 1
+/*
+ Goes recursively through the neighbours of the node.
+
+ Alters only transparent nodes.
+
+ If the lighting of the neighbour is lower than the lighting of
+ the node was (before changing it to 0 at the step before), the
+ lighting of the neighbour is set to 0 and then the same stuff
+ repeats for the neighbour.
+
+ The ending nodes of the routine are stored in light_sources.
+ This is useful when a light is removed. In such case, this
+ routine can be called for the light node and then again for
+ light_sources to re-light the area without the removed light.
+
+ values of from_nodes are lighting values.
+*/
+void VoxelManipulator::unspreadLight(enum LightBank bank,
+ core::map<v3s16, u8> & from_nodes,
+ core::map<v3s16, bool> & light_sources)
+{
+ if(from_nodes.size() == 0)
+ return;
+
+ core::map<v3s16, u8>::Iterator j;
+ j = from_nodes.getIterator();
+
+ for(; j.atEnd() == false; j++)
+ {
+ v3s16 pos = j.getNode()->getKey();
+
+ //MapNode &n = m_data[m_area.index(pos)];
+
+ u8 oldlight = j.getNode()->getValue();
+
+ unspreadLight(bank, pos, oldlight, light_sources);
+ }
+}
+#endif
+
+#if 0
+/*
+ Goes recursively through the neighbours of the node.
+
+ Alters only transparent nodes.
+
+ If the lighting of the neighbour is lower than the lighting of
+ the node was (before changing it to 0 at the step before), the
+ lighting of the neighbour is set to 0 and then the same stuff
+ repeats for the neighbour.
+
+ The ending nodes of the routine are stored in light_sources.
+ This is useful when a light is removed. In such case, this
+ routine can be called for the light node and then again for
+ light_sources to re-light the area without the removed light.
+
+ values of from_nodes are lighting values.
+*/
+void VoxelManipulator::unspreadLight(enum LightBank bank,
+ core::map<v3s16, u8> & from_nodes,
+ core::map<v3s16, bool> & light_sources)
+{
+ v3s16 dirs[6] = {
+ v3s16(0,0,1), // back
+ v3s16(0,1,0), // top
+ v3s16(1,0,0), // right
+ v3s16(0,0,-1), // front
+ v3s16(0,-1,0), // bottom
+ v3s16(-1,0,0), // left
+ };
+
+ if(from_nodes.size() == 0)
+ return;
+
+ core::map<v3s16, u8> unlighted_nodes;
+ core::map<v3s16, u8>::Iterator j;
+ j = from_nodes.getIterator();
+
+ for(; j.atEnd() == false; j++)
+ {
+ v3s16 pos = j.getNode()->getKey();
+
+ emerge(VoxelArea(pos - v3s16(1,1,1), pos + v3s16(1,1,1)));
+
+ //MapNode &n = m_data[m_area.index(pos)];
+
+ u8 oldlight = j.getNode()->getValue();
+
+ // Loop through 6 neighbors
+ for(u16 i=0; i<6; i++)
+ {
+ // Get the position of the neighbor node
+ v3s16 n2pos = pos + dirs[i];
+
+ u32 n2i = m_area.index(n2pos);
+
+ if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+ continue;
+
+ MapNode &n2 = m_data[n2i];
+
+ /*
+ If the neighbor is dimmer than what was specified
+ as oldlight (the light of the previous node)
+ */
+ if(n2.getLight(bank) < oldlight)
+ {
+ /*
+ And the neighbor is transparent and it has some light
+ */
+ if(n2.light_propagates() && n2.getLight(bank) != 0)
+ {
+ /*
+ Set light to 0 and add to queue
+ */
+
+ u8 current_light = n2.getLight(bank);
+ n2.setLight(bank, 0);
+
+ unlighted_nodes.insert(n2pos, current_light);
+
+ /*
+ Remove from light_sources if it is there
+ NOTE: This doesn't happen nearly at all
+ */
+ /*if(light_sources.find(n2pos))
+ {
+ std::cout<<"Removed from light_sources"<<std::endl;
+ light_sources.remove(n2pos);
+ }*/
+ }
+ }
+ else{
+ light_sources.insert(n2pos, true);
+ }
+ }
+ }
+
+ /*dstream<<"unspreadLight(): Changed block "
+ <<blockchangecount<<" times"
+ <<" for "<<from_nodes.size()<<" nodes"
+ <<std::endl;*/
+
+ if(unlighted_nodes.size() > 0)
+ unspreadLight(bank, unlighted_nodes, light_sources);
+}
+#endif
+
+void VoxelManipulator::spreadLight(enum LightBank bank, v3s16 p)
+{
+ const v3s16 dirs[6] = {
+ v3s16(0,0,1), // back
+ v3s16(0,1,0), // top
+ v3s16(1,0,0), // right
+ v3s16(0,0,-1), // front
+ v3s16(0,-1,0), // bottom
+ v3s16(-1,0,0), // left
+ };
+
+ emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)));
+
+ u32 i = m_area.index(p);
+
+ if(m_flags[i] & VOXELFLAG_INEXISTENT)
+ return;
+
+ MapNode &n = m_data[i];
+
+ u8 oldlight = n.getLight(bank);
+ u8 newlight = diminish_light(oldlight);
+
+ // Loop through 6 neighbors
+ for(u16 i=0; i<6; i++)
+ {
+ // Get the position of the neighbor node
+ v3s16 n2pos = p + dirs[i];
+
+ u32 n2i = m_area.index(n2pos);
+
+ if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+ continue;
+
+ MapNode &n2 = m_data[n2i];
+
+ /*
+ If the neighbor is brighter than the current node,
+ add to list (it will light up this node on its turn)
+ */
+ if(n2.getLight(bank) > undiminish_light(oldlight))
+ {
+ spreadLight(bank, n2pos);
+ }
+ /*
+ If the neighbor is dimmer than how much light this node
+ would spread on it, add to list
+ */
+ if(n2.getLight(bank) < newlight)
+ {
+ if(n2.light_propagates())
+ {
+ n2.setLight(bank, newlight);
+ spreadLight(bank, n2pos);
+ }
+ }
+ }
+}
+
+#if 1
+/*
+ Lights neighbors of from_nodes, collects all them and then
+ goes on recursively.
+*/
+void VoxelManipulator::spreadLight(enum LightBank bank,
+ core::map<v3s16, bool> & from_nodes)
+{
+ if(from_nodes.size() == 0)
+ return;
+
+ core::map<v3s16, bool> lighted_nodes;
+ core::map<v3s16, bool>::Iterator j;
+ j = from_nodes.getIterator();
+
+ for(; j.atEnd() == false; j++)
+ {
+ v3s16 pos = j.getNode()->getKey();
+
+ spreadLight(bank, pos);
+ }
+}
+#endif
+
+#if 0
+/*
+ Lights neighbors of from_nodes, collects all them and then
+ goes on recursively.
+*/
+void VoxelManipulator::spreadLight(enum LightBank bank,
+ core::map<v3s16, bool> & from_nodes)
+{
+ const v3s16 dirs[6] = {
+ v3s16(0,0,1), // back
+ v3s16(0,1,0), // top
+ v3s16(1,0,0), // right
+ v3s16(0,0,-1), // front
+ v3s16(0,-1,0), // bottom
+ v3s16(-1,0,0), // left
+ };
+
+ if(from_nodes.size() == 0)
+ return;
+
+ core::map<v3s16, bool> lighted_nodes;
+ core::map<v3s16, bool>::Iterator j;
+ j = from_nodes.getIterator();
+
+ for(; j.atEnd() == false; j++)
+ {
+ v3s16 pos = j.getNode()->getKey();
+
+ emerge(VoxelArea(pos - v3s16(1,1,1), pos + v3s16(1,1,1)));
+
+ u32 i = m_area.index(pos);
+
+ if(m_flags[i] & VOXELFLAG_INEXISTENT)
+ continue;
+
+ MapNode &n = m_data[i];
+
+ u8 oldlight = n.getLight(bank);
+ u8 newlight = diminish_light(oldlight);
+
+ // Loop through 6 neighbors
+ for(u16 i=0; i<6; i++)
+ {
+ // Get the position of the neighbor node
+ v3s16 n2pos = pos + dirs[i];
+
+ try
+ {
+ u32 n2i = m_area.index(n2pos);
+
+ if(m_flags[n2i] & VOXELFLAG_INEXISTENT)
+ continue;
+
+ MapNode &n2 = m_data[n2i];
+
+ /*
+ If the neighbor is brighter than the current node,
+ add to list (it will light up this node on its turn)
+ */
+ if(n2.getLight(bank) > undiminish_light(oldlight))
+ {
+ lighted_nodes.insert(n2pos, true);
+ }
+ /*
+ If the neighbor is dimmer than how much light this node
+ would spread on it, add to list
+ */
+ if(n2.getLight(bank) < newlight)
+ {
+ if(n2.light_propagates())
+ {
+ n2.setLight(bank, newlight);
+ lighted_nodes.insert(n2pos, true);
+ }
+ }
+ }
+ catch(InvalidPositionException &e)
+ {
+ continue;
+ }
+ }
+ }
+
+ /*dstream<<"spreadLight(): Changed block "
+ <<blockchangecount<<" times"
+ <<" for "<<from_nodes.size()<<" nodes"
+ <<std::endl;*/
+
+ if(lighted_nodes.size() > 0)
+ spreadLight(bank, lighted_nodes);
+}
+#endif
+
#if 0
int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count)
{
diff --git a/src/voxel.h b/src/voxel.h
index c377dfe7a..80d292891 100644
--- a/src/voxel.h
+++ b/src/voxel.h
@@ -323,7 +323,11 @@ public:
emerge(p);
return !(m_flags[m_area.index(p)] & VOXELFLAG_INEXISTENT);
}*/
- // These are a bit slow and shouldn't be used internally
+
+ /*
+ These are a bit slow and shouldn't be used internally.
+ Use m_data[m_area.index(p)] instead.
+ */
MapNode getNode(v3s16 p)
{
emerge(p);
@@ -396,7 +400,17 @@ public:
*/
void clearFlag(u8 flag);
-
+
+ void unspreadLight(enum LightBank bank, v3s16 p, u8 oldlight,
+ core::map<v3s16, bool> & light_sources);
+ void unspreadLight(enum LightBank bank,
+ core::map<v3s16, u8> & from_nodes,
+ core::map<v3s16, bool> & light_sources);
+
+ void spreadLight(enum LightBank bank, v3s16 p);
+ void spreadLight(enum LightBank bank,
+ core::map<v3s16, bool> & from_nodes);
+
#if 0
// VOXELFLAG_CHECKED2s must usually be cleared before calling
// -1: dead end, 0-255: pressure