forked from Mirrorlandia_minetest/minetest
Faster lighting at map generation time
This commit is contained in:
parent
87554408ca
commit
3909e712a0
@ -47,6 +47,7 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("objectdata_interval", "0.2");
|
g_settings.setDefault("objectdata_interval", "0.2");
|
||||||
g_settings.setDefault("active_object_range", "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", "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_simultaneous_block_sends_server_total", "4");
|
||||||
g_settings.setDefault("max_block_send_distance", "6");
|
g_settings.setDefault("max_block_send_distance", "6");
|
||||||
g_settings.setDefault("max_block_generate_distance", "6");
|
g_settings.setDefault("max_block_generate_distance", "6");
|
||||||
|
@ -259,7 +259,8 @@ TODO: Remove HMParams
|
|||||||
|
|
||||||
TODO: Flowing water to actually contain flow direction information
|
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:
|
Doing now:
|
||||||
----------
|
----------
|
||||||
|
139
src/map.cpp
139
src/map.cpp
@ -622,10 +622,13 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
core::map<v3s16, MapBlock*> & modified_blocks)
|
core::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
{
|
{
|
||||||
/*m_dout<<DTIME<<"Map::updateLighting(): "
|
/*m_dout<<DTIME<<"Map::updateLighting(): "
|
||||||
<<a_blocks.getSize()<<" blocks... ";*/
|
<<a_blocks.size()<<" blocks."<<std::endl;*/
|
||||||
|
|
||||||
|
//TimeTaker timer("updateLighting");
|
||||||
|
|
||||||
// For debugging
|
// For debugging
|
||||||
bool debug=false;
|
bool debug=true;
|
||||||
|
|
||||||
u32 count_was = modified_blocks.size();
|
u32 count_was = modified_blocks.size();
|
||||||
|
|
||||||
core::map<v3s16, bool> light_sources;
|
core::map<v3s16, bool> light_sources;
|
||||||
@ -721,8 +724,9 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
//TimeTaker timer("unspreadLight");
|
TimeTaker timer("unspreadLight");
|
||||||
unspreadLight(bank, unlight_from, light_sources, modified_blocks);
|
unspreadLight(bank, unlight_from, light_sources, modified_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,7 +745,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
// - Find out why it works
|
// - Find out why it works
|
||||||
|
|
||||||
{
|
{
|
||||||
//TimeTaker timer("spreadLight");
|
TimeTaker timer("spreadLight");
|
||||||
spreadLight(bank, light_sources, modified_blocks);
|
spreadLight(bank, light_sources, modified_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,6 +755,36 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
count_was = modified_blocks.size();
|
count_was = modified_blocks.size();
|
||||||
dstream<<"spreadLight modified "<<diff<<std::endl;
|
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;
|
//m_dout<<"Done ("<<getTimestamp()<<")"<<std::endl;
|
||||||
}
|
}
|
||||||
@ -2220,7 +2254,8 @@ MapBlock * ServerMap::emergeBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//dstream<<"Not found on disk, generating."<<std::endl;
|
//dstream<<"Not found on disk, generating."<<std::endl;
|
||||||
//TimeTaker("emergeBlock()", g_irrlicht);
|
// 0ms
|
||||||
|
//TimeTaker("emergeBlock() generate");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do not generate over-limit
|
Do not generate over-limit
|
||||||
@ -4138,7 +4173,10 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void MapVoxelManipulator::emerge(VoxelArea a)
|
/*
|
||||||
|
NOTE: This is slow
|
||||||
|
*/
|
||||||
|
void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
|
||||||
{
|
{
|
||||||
TimeTaker timer1("emerge", &emerge_time);
|
TimeTaker timer1("emerge", &emerge_time);
|
||||||
|
|
||||||
@ -4186,6 +4224,9 @@ void MapVoxelManipulator::blitBack
|
|||||||
|
|
||||||
//TimeTaker timer1("blitBack");
|
//TimeTaker timer1("blitBack");
|
||||||
|
|
||||||
|
/*dstream<<"blitBack(): m_loaded_blocks.size()="
|
||||||
|
<<m_loaded_blocks.size()<<std::endl;*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialize block cache
|
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
|
//END
|
||||||
|
15
src/map.h
15
src/map.h
@ -523,7 +523,7 @@ public:
|
|||||||
|
|
||||||
void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
|
void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Map *m_map;
|
Map *m_map;
|
||||||
/*
|
/*
|
||||||
NOTE: This might be used or not
|
NOTE: This might be used or not
|
||||||
@ -534,5 +534,18 @@ private:
|
|||||||
core::map<v3s16, bool> m_loaded_blocks;
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -412,8 +412,9 @@ void LocalPlayer::applyControl(float dtime)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
speed += move_direction;
|
// "Turbo button"
|
||||||
superspeed = true;
|
/*speed += move_direction;
|
||||||
|
superspeed = true;*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ void * EmergeThread::Thread()
|
|||||||
changed_blocks,
|
changed_blocks,
|
||||||
lighting_invalidated_blocks);
|
lighting_invalidated_blocks);
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
/*
|
/*
|
||||||
EXPERIMENTAL: Create a few other blocks too
|
EXPERIMENTAL: Create a few other blocks too
|
||||||
*/
|
*/
|
||||||
@ -184,6 +184,19 @@ void * EmergeThread::Thread()
|
|||||||
only_from_disk,
|
only_from_disk,
|
||||||
changed_blocks,
|
changed_blocks,
|
||||||
lighting_invalidated_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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,23 +229,6 @@ void * EmergeThread::Thread()
|
|||||||
dout_server<<std::endl;
|
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
|
Collect a list of blocks that have been modified in
|
||||||
addition to the fetched one.
|
addition to the fetched one.
|
||||||
@ -249,7 +245,7 @@ void * EmergeThread::Thread()
|
|||||||
/*dstream<<"lighting "<<lighting_invalidated_blocks.size()
|
/*dstream<<"lighting "<<lighting_invalidated_blocks.size()
|
||||||
<<" blocks"<<std::endl;*/
|
<<" blocks"<<std::endl;*/
|
||||||
|
|
||||||
//TimeTaker timer("** updateLighting", g_device);
|
//TimeTaker timer("** updateLighting");
|
||||||
|
|
||||||
// Update lighting without locking the environment mutex,
|
// Update lighting without locking the environment mutex,
|
||||||
// add modified blocks to changed blocks
|
// add modified blocks to changed blocks
|
||||||
@ -498,6 +494,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
|
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// If this is true, inexistent block will be made from scratch
|
||||||
bool generate = d <= d_max_gen;
|
bool generate = d <= d_max_gen;
|
||||||
|
|
||||||
if(haxmode)
|
if(haxmode)
|
||||||
@ -513,6 +510,35 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
generate = false;
|
generate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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
|
Don't draw if not in sight
|
||||||
*/
|
*/
|
||||||
|
389
src/voxel.cpp
389
src/voxel.cpp
@ -264,6 +264,395 @@ void VoxelManipulator::clearFlag(u8 flags)
|
|||||||
<<volume<<" nodes"<<std::endl;*/
|
<<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
|
#if 0
|
||||||
int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count)
|
int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count)
|
||||||
{
|
{
|
||||||
|
16
src/voxel.h
16
src/voxel.h
@ -323,7 +323,11 @@ public:
|
|||||||
emerge(p);
|
emerge(p);
|
||||||
return !(m_flags[m_area.index(p)] & VOXELFLAG_INEXISTENT);
|
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)
|
MapNode getNode(v3s16 p)
|
||||||
{
|
{
|
||||||
emerge(p);
|
emerge(p);
|
||||||
@ -397,6 +401,16 @@ public:
|
|||||||
|
|
||||||
void clearFlag(u8 flag);
|
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
|
#if 0
|
||||||
// VOXELFLAG_CHECKED2s must usually be cleared before calling
|
// VOXELFLAG_CHECKED2s must usually be cleared before calling
|
||||||
// -1: dead end, 0-255: pressure
|
// -1: dead end, 0-255: pressure
|
||||||
|
Loading…
Reference in New Issue
Block a user