From 0f3c2f65414f332fad510fb8651dd59d506aad2e Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 27 Jan 2012 13:24:06 +0200 Subject: voxalgo::clearLightAndCollectSources --- src/map.cpp | 15 ++++++++++---- src/mapgen.cpp | 5 +++++ src/test.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ src/voxelalgorithms.cpp | 41 ++++++++++++++++++++++++++++++++----- src/voxelalgorithms.h | 6 ++++++ 5 files changed, 112 insertions(+), 9 deletions(-) (limited to 'src') 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; -- cgit v1.2.3 om">This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "helper.h" #include <cmath> #include <sstream> #include <irr_v2d.h> #include "c_types.h" #include "c_internal.h" // imported from c_converter.cpp with pure C++ style static inline void check_lua_type(lua_State *L, int index, const char *name, int type) { int t = lua_type(L, index); if (t != type) { std::string traceback = script_get_backtrace(L); throw LuaError(std::string("Invalid ") + (name) + " (expected " + lua_typename(L, (type)) + " got " + lua_typename(L, t) + ").\n" + traceback); } } // imported from c_converter.cpp #define CHECK_POS_COORD(name) \ check_lua_type(L, -1, "position coordinate '" name "'", LUA_TNUMBER) #define CHECK_POS_TAB(index) check_lua_type(L, index, "position", LUA_TTABLE) bool LuaHelper::isNaN(lua_State *L, int idx) { return lua_type(L, idx) == LUA_TNUMBER && std::isnan(lua_tonumber(L, idx)); } /* * Read template functions */ template <> bool LuaHelper::readParam(lua_State *L, int index) { return lua_toboolean(L, index) != 0; } template <> bool LuaHelper::readParam(lua_State *L, int index, const bool &default_value) { if (lua_isnil(L, index)) return default_value; return lua_toboolean(L, index) != 0; } template <> s16 LuaHelper::readParam(lua_State *L, int index) { return lua_tonumber(L, index); } template <> float LuaHelper::readParam(lua_State *L, int index) { if (isNaN(L, index)) throw LuaError("NaN value is not allowed."); return (float)luaL_checknumber(L, index); } template <> v2s16 LuaHelper::readParam(lua_State *L, int index) { v2s16 p; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); CHECK_POS_COORD("x"); p.X = readParam<s16>(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); CHECK_POS_COORD("y"); p.Y = readParam<s16>(L, -1); lua_pop(L, 1); return p; } template <> v2f LuaHelper::readParam(lua_State *L, int index) { v2f p; CHECK_POS_TAB(index); lua_getfield(L, index, "x"); CHECK_POS_COORD("x"); p.X = readParam<float>(L, -1); lua_pop(L, 1); lua_getfield(L, index, "y"); CHECK_POS_COORD("y"); p.Y = readParam<float>(L, -1); lua_pop(L, 1); return p; } template <> std::string LuaHelper::readParam(lua_State *L, int index) { std::string result; const char *str = luaL_checkstring(L, index); result.append(str); return result; } template <> std::string LuaHelper::readParam( lua_State *L, int index, const std::string &default_value) { std::string result; const char *str = lua_tostring(L, index); if (str) result.append(str); else result = default_value; return result; }