summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDániel Juhász <juhdanad@gmail.com>2016-10-23 17:51:13 +0200
committerNer'zhul <nerzhul@users.noreply.github.com>2016-10-27 08:04:42 +0200
commitbe39f61359ad63f2c6d4aea14c1dfd8357eee03f (patch)
tree17209bda6ba8e178b37f55dc479a91d981609cd7
parentc071efaa43ad3dcba7d60a7a67e942aae2a7dc83 (diff)
downloadminetest-be39f61359ad63f2c6d4aea14c1dfd8357eee03f.tar.gz
minetest-be39f61359ad63f2c6d4aea14c1dfd8357eee03f.tar.bz2
minetest-be39f61359ad63f2c6d4aea14c1dfd8357eee03f.zip
Use node lighting for liquid spreading
This commit modifies the liquid transforming procedure to light and unlight nodes instead of whole map blocks.
-rw-r--r--src/map.cpp23
-rw-r--r--src/voxelalgorithms.cpp229
-rw-r--r--src/voxelalgorithms.h13
3 files changed, 144 insertions, 121 deletions
diff --git a/src/map.cpp b/src/map.cpp
index 1694582db..5a1611c89 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -824,10 +824,15 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
}
// 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);
// 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
i = modified_blocks.begin();
@@ -1224,7 +1229,9 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
std::deque<v3s16> must_reflow;
// 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 loop_max = liquid_loop_max;
@@ -1457,6 +1464,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
}
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
std::string suspect;
if (m_gamedef->rollback())
@@ -1484,9 +1495,10 @@ void Map::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks)
if (block != NULL) {
modified_blocks[blockpos] = block;
// 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)
- 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)
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);
/* ----------------------------------------------------------------------
diff --git a/src/voxelalgorithms.cpp b/src/voxelalgorithms.cpp
index 019ec1bc6..83c1dd4ca 100644
--- a/src/voxelalgorithms.cpp
+++ b/src/voxelalgorithms.cpp
@@ -583,144 +583,153 @@ bool isSunlightAbove(Map *map, v3s16 pos, INodeDefManager *ndef)
static const LightBank banks[] = { LIGHTBANK_DAY, LIGHTBANK_NIGHT };
-void update_lighting_node(Map *map, INodeDefManager *ndef, v3s16 p,
- MapNode oldnode, std::map<v3s16, MapBlock*> & modified_blocks)
+void update_lighting_nodes(Map *map, INodeDefManager *ndef,
+ std::vector<std::pair<v3s16, MapNode> > &oldnodes,
+ std::map<v3s16, MapBlock*> & modified_blocks)
{
// For node getter functions
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
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];
+ 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
- u8 old_light = oldnode.getLight(bank, ndef);
+ // Light of the old node
+ u8 old_light = it->second.getLight(bank, ndef);
- // Add the block of the added node to modified_blocks
- modified_blocks[block_pos] = block;
+ // Add the block of the added node to modified_blocks
+ modified_blocks[block_pos] = block;
- // Get new light level of the node
- u8 new_light = 0;
- if (ndef->get(n).light_propagates) {
- if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
+ // Get new light level of the node
+ u8 new_light = 0;
+ if (ndef->get(n).light_propagates) {
+ if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
&& isSunlightAbove(map, p, ndef)) {
- new_light = LIGHT_SUN;
- } else {
- new_light = ndef->get(n).light_source;
- for (int i = 0; i < 6; i++) {
- v3s16 p2 = p + neighbor_dirs[i];
- bool is_valid;
- MapNode n2 = map->getNodeNoEx(p2, &is_valid);
- if (is_valid) {
- u8 spread = n2.getLight(bank, ndef);
- // If the neighbor is at least as bright as
- // this node then its light is not from
- // this node.
- // Its light can spread to this node.
- if (spread > new_light && spread >= old_light) {
- new_light = spread - 1;
+ new_light = LIGHT_SUN;
+ } else {
+ new_light = ndef->get(n).light_source;
+ for (int i = 0; i < 6; i++) {
+ v3s16 p2 = p + neighbor_dirs[i];
+ bool is_valid;
+ MapNode n2 = map->getNodeNoEx(p2, &is_valid);
+ if (is_valid) {
+ u8 spread = n2.getLight(bank, ndef);
+ // If the neighbor is at least as bright as
+ // this node then its light is not from
+ // this node.
+ // Its light can spread to this node.
+ if (spread > new_light && spread >= old_light) {
+ 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) {
+ light_sources.push(new_light, rel_pos, block_pos, block, 6);
+ }
- if (new_light < old_light) {
- // The node became opaque or doesn't provide as much
- // light as the previous one, so it must be unlighted.
- LightQueue disappearing_lights(256);
+ if (new_light < old_light) {
+ // The node became opaque or doesn't provide as much
+ // light as the previous one, so it must be unlighted.
- // Add to unlight queue
- n.setLight(bank, 0, ndef);
- block->setNodeNoCheck(rel_pos, n);
- disappearing_lights.push(old_light, rel_pos, block_pos, block, 6);
+ // Add to unlight queue
+ n.setLight(bank, 0, ndef);
+ block->setNodeNoCheck(rel_pos, n);
+ disappearing_lights.push(old_light, rel_pos, block_pos, block,
+ 6);
- // Remove sunlight, if there was any
- if (bank == LIGHTBANK_DAY && old_light == LIGHT_SUN) {
- for (s16 y = p.Y - 1;; y--) {
- v3s16 n2pos(p.X, y, p.Z);
+ // Remove sunlight, if there was any
+ if (bank == LIGHTBANK_DAY && old_light == LIGHT_SUN) {
+ for (s16 y = p.Y - 1;; y--) {
+ v3s16 n2pos(p.X, y, p.Z);
- MapNode n2;
+ MapNode n2;
- n2 = map->getNodeNoEx(n2pos, &is_valid_position);
- if (!is_valid_position)
- break;
+ n2 = map->getNodeNoEx(n2pos, &is_valid_position);
+ if (!is_valid_position)
+ break;
- // If this node doesn't have sunlight, the nodes below
- // it don't have too.
- if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
- break;
+ // If this node doesn't have sunlight, the nodes below
+ // it don't have too.
+ if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
+ break;
+ }
+ // 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 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;
+ } 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);
}
- 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.
for (u8 i = 0; i <= LIGHT_SUN; i++) {
const std::vector<ChangingLight> &lights = light_sources.lights[i];
diff --git a/src/voxelalgorithms.h b/src/voxelalgorithms.h
index f2b2fde32..3632546dd 100644
--- a/src/voxelalgorithms.h
+++ b/src/voxelalgorithms.h
@@ -58,18 +58,19 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
/*!
* Updates the lighting on the map.
* 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 oldnode this node was overwritten on the map
+ * \param oldnodes contains the MapNodes that were replaced by the new
+ * MapNodes and their positions
* \param modified_blocks output, contains all map blocks that
* the function modified
*/
-void update_lighting_node(
+void update_lighting_nodes(
Map *map,
INodeDefManager *ndef,
- v3s16 p,
- MapNode oldnode,
+ std::vector<std::pair<v3s16, MapNode> > &oldnodes,
std::map<v3s16, MapBlock*> &modified_blocks);
} // namespace voxalgo