diff options
Diffstat (limited to 'src/voxelalgorithms.cpp')
-rw-r--r-- | src/voxelalgorithms.cpp | 229 |
1 files changed, 119 insertions, 110 deletions
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]; |