mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Use node lighting for liquid spreading
This commit modifies the liquid transforming procedure to light and unlight nodes instead of whole map blocks.
This commit is contained in:
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
|
||||
// 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);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
@ -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.
|
||||
|
||||
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);
|
||||
// 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 */);
|
||||
}
|
||||
}
|
||||
} 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.
|
||||
for (u8 i = 0; i <= LIGHT_SUN; 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.
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user