diff --git a/src/map.cpp b/src/map.cpp index dce3bdc09..1ab2b32ae 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -690,9 +690,11 @@ void Map::updateLighting(enum LightBank bank, core::map light_sources; core::map unlight_from; + + int num_bottom_invalid = 0; { - //TimeTaker t("first stuff"); + TimeTaker t("first stuff"); core::map::Iterator i; i = a_blocks.getIterator(); @@ -758,6 +760,9 @@ void Map::updateLighting(enum LightBank bank, { bool bottom_valid = block->propagateSunlight(light_sources); + if(!bottom_valid) + num_bottom_invalid++; + // If bottom is valid, we're done. if(bottom_valid) break; @@ -792,6 +797,8 @@ void Map::updateLighting(enum LightBank bank, } } + + infostream<<"num_bottom_invalid="<registerItem(itemdef); ndef->set(i, f); + + /* + Torch (minimal definition for lighting tests) + */ + i = CONTENT_TORCH; + itemdef = ItemDefinition(); + itemdef.type = ITEM_NODE; + itemdef.name = "default:torch"; + f = ContentFeatures(); + f.name = itemdef.name; + f.param_type = CPT_LIGHT; + f.light_propagates = true; + f.sunlight_propagates = true; + f.light_source = LIGHT_MAX-1; + idef->registerItem(itemdef); + ndef->set(i, f); } struct TestUtilities @@ -488,6 +505,9 @@ struct TestVoxelAlgorithms { void Run(INodeDefManager *ndef) { + /* + voxalgo::propagateSunlight + */ { VoxelManipulator v; for(u16 z=0; z<3; z++) @@ -593,6 +613,40 @@ struct TestVoxelAlgorithms assert(res.bottom_sunlight_valid == true); } } + /* + voxalgo::clearLightAndCollectSources + */ + { + VoxelManipulator v; + for(u16 z=0; z<3; z++) + for(u16 y=0; y<3; y++) + for(u16 x=0; x<3; x++) + { + v3s16 p(x,y,z); + v.setNode(p, MapNode(CONTENT_AIR)); + } + VoxelArea a(v3s16(0,0,0), v3s16(2,2,2)); + v.setNodeNoRef(v3s16(0,0,0), MapNode(CONTENT_STONE)); + v.setNodeNoRef(v3s16(1,1,1), MapNode(CONTENT_TORCH)); + { + MapNode n(CONTENT_AIR); + n.setLight(LIGHTBANK_DAY, 1, ndef); + v.setNode(v3s16(1,1,2), n); + } + { + core::map light_sources; + core::map unlight_from; + voxalgo::clearLightAndCollectSources(v, a, LIGHTBANK_DAY, + ndef, light_sources, unlight_from); + //v.print(dstream, ndef, VOXELPRINT_LIGHT_DAY); + assert(v.getNode(v3s16(0,1,1)).getLight(LIGHTBANK_DAY, ndef) + == 0); + assert(light_sources.find(v3s16(1,1,1)) != NULL); + assert(light_sources.size() == 1); + assert(unlight_from.find(v3s16(1,1,2)) != NULL); + assert(unlight_from.size() == 1); + } + } } }; diff --git a/src/voxelalgorithms.cpp b/src/voxelalgorithms.cpp index ae609e96a..ab6cbdfa2 100644 --- a/src/voxelalgorithms.cpp +++ b/src/voxelalgorithms.cpp @@ -37,6 +37,42 @@ void setLight(VoxelManipulator &v, VoxelArea a, u8 light, } } +void clearLightAndCollectSources(VoxelManipulator &v, VoxelArea a, + enum LightBank bank, INodeDefManager *ndef, + core::map & light_sources, + core::map & unlight_from) +{ + // The full area we shall touch + VoxelArea required_a = a; + required_a.pad(v3s16(0,0,0)); + // Make sure we have access to it + v.emerge(a); + + for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++) + for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++) + for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++) + { + v3s16 p(x,y,z); + MapNode &n = v.getNodeRefUnsafe(p); + u8 oldlight = n.getLight(bank, ndef); + n.setLight(bank, 0, ndef); + + // If node sources light, add to list + u8 source = ndef->get(n).light_source; + if(source != 0) + light_sources[p] = true; + + // Collect borders for unlighting + if((x==a.MinEdge.X || x == a.MaxEdge.X + || y==a.MinEdge.Y || y == a.MaxEdge.Y + || z==a.MinEdge.Z || z == a.MaxEdge.Z) + && oldlight != 0) + { + unlight_from.insert(p, oldlight); + } + } +} + SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a, bool inexistent_top_provides_sunlight, core::map & light_sources, @@ -69,11 +105,6 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a, overtop_has_sunlight = (v.getNodeRefUnsafe(p_overtop).getLight( LIGHTBANK_DAY, ndef) == LIGHT_SUN); - dstream<<"inexistent_top_provides_sunlight=" - < & light_sources, + core::map & unlight_from); + struct SunlightPropagateResult { bool bottom_sunlight_valid;