1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Faster lighting at map generation time

This commit is contained in:
Perttu Ahola 2011-01-24 16:36:58 +02:00
parent 87554408ca
commit 3909e712a0
8 changed files with 605 additions and 33 deletions

View file

@ -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)
{