Use node lighting for liquid spreading
This commit modifies the liquid transforming procedure to light and unlight nodes instead of whole map blocks.master
parent
c071efaa43
commit
be39f61359
23
src/map.cpp
23
src/map.cpp
|
@ -824,10 +824,15 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the node on the map
|
// Set the node on the map
|
||||||
|
// Ignore light (because calling voxalgo::update_lighting_nodes)
|
||||||
|
n.setLight(LIGHTBANK_DAY, 0, ndef);
|
||||||
|
n.setLight(LIGHTBANK_NIGHT, 0, ndef);
|
||||||
setNode(p, n);
|
setNode(p, n);
|
||||||
|
|
||||||
// Update lighting
|
// Update lighting
|
||||||
voxalgo::update_lighting_node(this, ndef, p, oldnode, modified_blocks);
|
std::vector<std::pair<v3s16, MapNode> > oldnodes;
|
||||||
|
oldnodes.push_back(std::pair<v3s16, MapNode>(p, oldnode));
|
||||||
|
voxalgo::update_lighting_nodes(this, ndef, oldnodes, modified_blocks);
|
||||||
|
|
||||||
for(std::map<v3s16, MapBlock*>::iterator
|
for(std::map<v3s16, MapBlock*>::iterator
|
||||||
i = modified_blocks.begin();
|
i = modified_blocks.begin();
|
||||||
|
@ -1224,7 +1229,9 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
|
||||||
std::deque<v3s16> must_reflow;
|
std::deque<v3s16> must_reflow;
|
||||||
|
|
||||||
// List of MapBlocks that will require a lighting update (due to lava)
|
// List of MapBlocks that will require a lighting update (due to lava)
|
||||||
std::map<v3s16, MapBlock *> lighting_modified_blocks;
|
std::map<v3s16, MapBlock *> lighting_modified_blocks2;
|
||||||
|
|
||||||
|
std::vector<std::pair<v3s16, MapNode> > changed_nodes;
|
||||||
|
|
||||||
u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
|
u32 liquid_loop_max = g_settings->getS32("liquid_loop_max");
|
||||||
u32 loop_max = liquid_loop_max;
|
u32 loop_max = liquid_loop_max;
|
||||||
|
@ -1457,6 +1464,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
|
||||||
}
|
}
|
||||||
n0.setContent(new_node_content);
|
n0.setContent(new_node_content);
|
||||||
|
|
||||||
|
// Ignore light (because calling voxalgo::update_lighting_nodes)
|
||||||
|
n0.setLight(LIGHTBANK_DAY, 0, nodemgr);
|
||||||
|
n0.setLight(LIGHTBANK_NIGHT, 0, nodemgr);
|
||||||
|
|
||||||
// Find out whether there is a suspect for this action
|
// Find out whether there is a suspect for this action
|
||||||
std::string suspect;
|
std::string suspect;
|
||||||
if (m_gamedef->rollback())
|
if (m_gamedef->rollback())
|
||||||
|
@ -1484,9 +1495,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
|
||||||
if (block != NULL) {
|
if (block != NULL) {
|
||||||
modified_blocks[blockpos] = block;
|
modified_blocks[blockpos] = block;
|
||||||
// If new or old node emits light, MapBlock requires lighting update
|
// If new or old node emits light, MapBlock requires lighting update
|
||||||
if (nodemgr->get(n0).light_source != 0 ||
|
/*if (nodemgr->get(n0).light_source != 0 ||
|
||||||
nodemgr->get(n00).light_source != 0)
|
nodemgr->get(n00).light_source != 0)
|
||||||
lighting_modified_blocks[block->getPos()] = block;
|
lighting_modified_blocks[block->getPos()] = block;*/
|
||||||
|
changed_nodes.push_back(std::pair<v3s16, MapNode>(p0, n00));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1515,7 +1527,8 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
|
||||||
for (std::deque<v3s16>::iterator iter = must_reflow.begin(); iter != must_reflow.end(); ++iter)
|
for (std::deque<v3s16>::iterator iter = must_reflow.begin(); iter != must_reflow.end(); ++iter)
|
||||||
m_transforming_liquid.push_back(*iter);
|
m_transforming_liquid.push_back(*iter);
|
||||||
|
|
||||||
updateLighting(lighting_modified_blocks, modified_blocks);
|
//updateLighting(lighting_modified_blocks, modified_blocks);
|
||||||
|
voxalgo::update_lighting_nodes(this, nodemgr, changed_nodes, modified_blocks);
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
|
|
|
@ -583,144 +583,153 @@ bool isSunlightAbove(Map *map, v3s16 pos, INodeDefManager *ndef)
|
||||||
|
|
||||||
static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT };
|
static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT };
|
||||||
|
|
||||||
void update_lighting_node(Map *map, INodeDefManager *ndef, v3s16 p,
|
void update_lighting_nodes(Map *map, INodeDefManager *ndef,
|
||||||
MapNode oldnode, std::map<v3s16, MapBlock*> & modified_blocks)
|
std::vector<std::pair<v3s16, MapNode> > &oldnodes,
|
||||||
|
std::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
{
|
{
|
||||||
// For node getter functions
|
// For node getter functions
|
||||||
bool is_valid_position;
|
bool is_valid_position;
|
||||||
|
|
||||||
// Get position and block of the changed node
|
|
||||||
relative_v3 rel_pos;
|
|
||||||
mapblock_v3 block_pos;
|
|
||||||
getNodeBlockPosWithOffset(p, block_pos, rel_pos);
|
|
||||||
MapBlock *block = map->getBlockNoCreateNoEx(block_pos);
|
|
||||||
if (block == NULL || block->isDummy()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process each light bank separately
|
// Process each light bank separately
|
||||||
for (s32 i = 0; i < 2; i++) {
|
for (s32 i = 0; i < 2; i++) {
|
||||||
// Get the new node
|
|
||||||
MapNode n = block->getNodeNoCheck(rel_pos, &is_valid_position);
|
|
||||||
if (!is_valid_position) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LightBank bank = banks[i];
|
LightBank bank = banks[i];
|
||||||
|
UnlightQueue disappearing_lights(256);
|
||||||
|
ReLightQueue light_sources(256);
|
||||||
|
// For each changed node process sunlight and initialize
|
||||||
|
for (std::vector<std::pair<v3s16, MapNode> >::iterator it =
|
||||||
|
oldnodes.begin(); it < oldnodes.end(); it++) {
|
||||||
|
// Get position and block of the changed node
|
||||||
|
v3s16 p = it->first;
|
||||||
|
relative_v3 rel_pos;
|
||||||
|
mapblock_v3 block_pos;
|
||||||
|
getNodeBlockPosWithOffset(p, block_pos, rel_pos);
|
||||||
|
MapBlock *block = map->getBlockNoCreateNoEx(block_pos);
|
||||||
|
if (block == NULL || block->isDummy()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Get the new node
|
||||||
|
MapNode n = block->getNodeNoCheck(rel_pos, &is_valid_position);
|
||||||
|
if (!is_valid_position) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Light of the old node
|
// Light of the old node
|
||||||
u8 old_light = oldnode.getLight(bank, ndef);
|
u8 old_light = it->second.getLight(bank, ndef);
|
||||||
|
|
||||||
// Add the block of the added node to modified_blocks
|
// Add the block of the added node to modified_blocks
|
||||||
modified_blocks[block_pos] = block;
|
modified_blocks[block_pos] = block;
|
||||||
|
|
||||||
// Get new light level of the node
|
// Get new light level of the node
|
||||||
u8 new_light = 0;
|
u8 new_light = 0;
|
||||||
if (ndef->get(n).light_propagates) {
|
if (ndef->get(n).light_propagates) {
|
||||||
if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
|
if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
|
||||||
&& isSunlightAbove(map, p, ndef)) {
|
&& isSunlightAbove(map, p, ndef)) {
|
||||||
new_light = LIGHT_SUN;
|
new_light = LIGHT_SUN;
|
||||||
} else {
|
} else {
|
||||||
new_light = ndef->get(n).light_source;
|
new_light = ndef->get(n).light_source;
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
v3s16 p2 = p + neighbor_dirs[i];
|
v3s16 p2 = p + neighbor_dirs[i];
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
MapNode n2 = map->getNodeNoEx(p2, &is_valid);
|
MapNode n2 = map->getNodeNoEx(p2, &is_valid);
|
||||||
if (is_valid) {
|
if (is_valid) {
|
||||||
u8 spread = n2.getLight(bank, ndef);
|
u8 spread = n2.getLight(bank, ndef);
|
||||||
// If the neighbor is at least as bright as
|
// If the neighbor is at least as bright as
|
||||||
// this node then its light is not from
|
// this node then its light is not from
|
||||||
// this node.
|
// this node.
|
||||||
// Its light can spread to this node.
|
// Its light can spread to this node.
|
||||||
if (spread > new_light && spread >= old_light) {
|
if (spread > new_light && spread >= old_light) {
|
||||||
new_light = spread - 1;
|
new_light = spread - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// If this is an opaque node, it still can emit light.
|
||||||
|
new_light = ndef->get(n).light_source;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If this is an opaque node, it still can emit light.
|
|
||||||
new_light = ndef->get(n).light_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReLightQueue light_sources(256);
|
if (new_light > 0) {
|
||||||
|
light_sources.push(new_light, rel_pos, block_pos, block, 6);
|
||||||
|
}
|
||||||
|
|
||||||
if (new_light > 0) {
|
if (new_light < old_light) {
|
||||||
light_sources.push(new_light, rel_pos, block_pos, block, 6);
|
// The node became opaque or doesn't provide as much
|
||||||
}
|
// light as the previous one, so it must be unlighted.
|
||||||
|
|
||||||
if (new_light < old_light) {
|
// Add to unlight queue
|
||||||
// The node became opaque or doesn't provide as much
|
n.setLight(bank, 0, ndef);
|
||||||
// light as the previous one, so it must be unlighted.
|
block->setNodeNoCheck(rel_pos, n);
|
||||||
LightQueue disappearing_lights(256);
|
disappearing_lights.push(old_light, rel_pos, block_pos, block,
|
||||||
|
6);
|
||||||
|
|
||||||
// Add to unlight queue
|
// Remove sunlight, if there was any
|
||||||
n.setLight(bank, 0, ndef);
|
if (bank == LIGHTBANK_DAY && old_light == LIGHT_SUN) {
|
||||||
block->setNodeNoCheck(rel_pos, n);
|
for (s16 y = p.Y - 1;; y--) {
|
||||||
disappearing_lights.push(old_light, rel_pos, block_pos, block, 6);
|
v3s16 n2pos(p.X, y, p.Z);
|
||||||
|
|
||||||
// Remove sunlight, if there was any
|
MapNode n2;
|
||||||
if (bank == LIGHTBANK_DAY && old_light == LIGHT_SUN) {
|
|
||||||
for (s16 y = p.Y - 1;; y--) {
|
|
||||||
v3s16 n2pos(p.X, y, p.Z);
|
|
||||||
|
|
||||||
MapNode n2;
|
n2 = map->getNodeNoEx(n2pos, &is_valid_position);
|
||||||
|
if (!is_valid_position)
|
||||||
|
break;
|
||||||
|
|
||||||
n2 = map->getNodeNoEx(n2pos, &is_valid_position);
|
// If this node doesn't have sunlight, the nodes below
|
||||||
if (!is_valid_position)
|
// it don't have too.
|
||||||
break;
|
if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
|
||||||
|
break;
|
||||||
// If this node doesn't have sunlight, the nodes below
|
}
|
||||||
// it don't have too.
|
// Remove sunlight and add to unlight queue.
|
||||||
if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
|
n2.setLight(LIGHTBANK_DAY, 0, ndef);
|
||||||
break;
|
map->setNode(n2pos, n2);
|
||||||
|
relative_v3 rel_pos2;
|
||||||
|
mapblock_v3 block_pos2;
|
||||||
|
getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
|
||||||
|
MapBlock *block2 = map->getBlockNoCreateNoEx(
|
||||||
|
block_pos2);
|
||||||
|
disappearing_lights.push(LIGHT_SUN, rel_pos2,
|
||||||
|
block_pos2, block2,
|
||||||
|
4 /* The node above caused the change */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (new_light > old_light) {
|
||||||
|
// It is sure that the node provides more light than the previous
|
||||||
|
// one, unlighting is not necessary.
|
||||||
|
// Propagate sunlight
|
||||||
|
if (bank == LIGHTBANK_DAY && new_light == LIGHT_SUN) {
|
||||||
|
for (s16 y = p.Y - 1;; y--) {
|
||||||
|
v3s16 n2pos(p.X, y, p.Z);
|
||||||
|
|
||||||
|
MapNode n2;
|
||||||
|
|
||||||
|
n2 = map->getNodeNoEx(n2pos, &is_valid_position);
|
||||||
|
if (!is_valid_position)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// This should not happen, but if the node has sunlight
|
||||||
|
// then the iteration should stop.
|
||||||
|
if (n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// If the node terminates sunlight, stop.
|
||||||
|
if (!ndef->get(n2).sunlight_propagates) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
relative_v3 rel_pos2;
|
||||||
|
mapblock_v3 block_pos2;
|
||||||
|
getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
|
||||||
|
MapBlock *block2 = map->getBlockNoCreateNoEx(
|
||||||
|
block_pos2);
|
||||||
|
// Mark node for lighting.
|
||||||
|
light_sources.push(LIGHT_SUN, rel_pos2, block_pos2,
|
||||||
|
block2, 4);
|
||||||
}
|
}
|
||||||
// Remove sunlight and add to unlight queue.
|
|
||||||
n2.setLight(LIGHTBANK_DAY, 0, ndef);
|
|
||||||
map->setNode(n2pos, n2);
|
|
||||||
relative_v3 rel_pos2;
|
|
||||||
mapblock_v3 block_pos2;
|
|
||||||
getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
|
|
||||||
MapBlock *block2 = map->getBlockNoCreateNoEx(block_pos2);
|
|
||||||
disappearing_lights.push(LIGHT_SUN, rel_pos2, block_pos2,
|
|
||||||
block2, 4 /* The node above caused the change */);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove lights
|
|
||||||
unspreadLight(map, ndef, bank, disappearing_lights, light_sources,
|
|
||||||
modified_blocks);
|
|
||||||
} else if (new_light > old_light) {
|
|
||||||
// It is sure that the node provides more light than the previous
|
|
||||||
// one, unlighting is not necessary.
|
|
||||||
// Propagate sunlight
|
|
||||||
if (bank == LIGHTBANK_DAY && new_light == LIGHT_SUN) {
|
|
||||||
for (s16 y = p.Y - 1;; y--) {
|
|
||||||
v3s16 n2pos(p.X, y, p.Z);
|
|
||||||
|
|
||||||
MapNode n2;
|
|
||||||
|
|
||||||
n2 = map->getNodeNoEx(n2pos, &is_valid_position);
|
|
||||||
if (!is_valid_position)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// This should not happen, but if the node has sunlight
|
|
||||||
// then the iteration should stop.
|
|
||||||
if (n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// If the node terminates sunlight, stop.
|
|
||||||
if (!ndef->get(n2).sunlight_propagates) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
relative_v3 rel_pos2;
|
|
||||||
mapblock_v3 block_pos2;
|
|
||||||
getNodeBlockPosWithOffset(n2pos, block_pos2, rel_pos2);
|
|
||||||
MapBlock *block2 = map->getBlockNoCreateNoEx(block_pos2);
|
|
||||||
// Mark node for lighting.
|
|
||||||
light_sources.push(LIGHT_SUN, rel_pos2, block_pos2, block2,
|
|
||||||
4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Remove lights
|
||||||
|
unspreadLight(map, ndef, bank, disappearing_lights, light_sources,
|
||||||
|
modified_blocks);
|
||||||
// Initialize light values for light spreading.
|
// Initialize light values for light spreading.
|
||||||
for (u8 i = 0; i <= LIGHT_SUN; i++) {
|
for (u8 i = 0; i <= LIGHT_SUN; i++) {
|
||||||
const std::vector<ChangingLight> &lights = light_sources.lights[i];
|
const std::vector<ChangingLight> &lights = light_sources.lights[i];
|
||||||
|
|
|
@ -58,18 +58,19 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
|
||||||
/*!
|
/*!
|
||||||
* Updates the lighting on the map.
|
* Updates the lighting on the map.
|
||||||
* The result will be correct only if
|
* The result will be correct only if
|
||||||
* no nodes were changed except the given one.
|
* no nodes were changed except the given ones.
|
||||||
|
* Before calling this procedure make sure that all new nodes on
|
||||||
|
* the map have zero light level!
|
||||||
*
|
*
|
||||||
* \param p position of the changed node
|
* \param oldnodes contains the MapNodes that were replaced by the new
|
||||||
* \param oldnode this node was overwritten on the map
|
* MapNodes and their positions
|
||||||
* \param modified_blocks output, contains all map blocks that
|
* \param modified_blocks output, contains all map blocks that
|
||||||
* the function modified
|
* the function modified
|
||||||
*/
|
*/
|
||||||
void update_lighting_node(
|
void update_lighting_nodes(
|
||||||
Map *map,
|
Map *map,
|
||||||
INodeDefManager *ndef,
|
INodeDefManager *ndef,
|
||||||
v3s16 p,
|
std::vector<std::pair<v3s16, MapNode> > &oldnodes,
|
||||||
MapNode oldnode,
|
|
||||||
std::map<v3s16, MapBlock*> &modified_blocks);
|
std::map<v3s16, MapBlock*> &modified_blocks);
|
||||||
|
|
||||||
} // namespace voxalgo
|
} // namespace voxalgo
|
||||||
|
|
Loading…
Reference in New Issue