diff options
-rw-r--r-- | src/mapgen.cpp | 117 | ||||
-rw-r--r-- | src/mapgen.h | 4 |
2 files changed, 113 insertions, 8 deletions
diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 156863170..699b51789 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -51,21 +51,19 @@ FlagDesc flagdesc_mapgen[] = { void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax) { bool isliquid, wasliquid; - u32 i; + v3s16 em = vm->m_area.getExtent(); for (s16 z = nmin.Z; z <= nmax.Z; z++) { for (s16 x = nmin.X; x <= nmax.X; x++) { - v2s16 p2d(x, z); wasliquid = true; - v3s16 em = vm->m_area.getExtent(); - i = vm->m_area.index(v3s16(p2d.X, nmax.Y, p2d.Y)); - + + u32 i = vm->m_area.index(x, nmax.Y, z); for (s16 y = nmax.Y; y >= nmin.Y; y--) { isliquid = ndef->get(vm->m_data[i]).isLiquid(); // there was a change between liquid and nonliquid, add to queue if (isliquid != wasliquid) - trans_liquid->push_back(v3s16(p2d.X, y, p2d.Y)); + trans_liquid->push_back(v3s16(x, y, z)); wasliquid = isliquid; vm->m_area.add_y(em, i, -1); @@ -75,7 +73,108 @@ void Mapgen::updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nm } +void Mapgen::setLighting(v3s16 nmin, v3s16 nmax, u8 light) { + ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); + VoxelArea a(nmin - v3s16(1,0,1) * MAP_BLOCKSIZE, + nmax + v3s16(1,0,1) * MAP_BLOCKSIZE); + + for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { + for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) { + u32 i = vm->m_area.index(a.MinEdge.X, y, z); + for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++) + vm->m_data[i].param1 = light; + } + } +} + + +void Mapgen::lightSpread(VoxelArea &a, v3s16 p, u8 light) { + if (light <= 1 || !a.contains(p)) + return; + + u32 vi = vm->m_area.index(p); + MapNode &nn = vm->m_data[vi]; + + light--; + // should probably compare masked, but doesn't seem to make a difference + if (light <= nn.param1 || !ndef->get(nn).light_propagates) + return; + + nn.param1 = light; + + lightSpread(a, p + v3s16(0, 0, 1), light); + lightSpread(a, p + v3s16(0, 1, 0), light); + lightSpread(a, p + v3s16(1, 0, 0), light); + lightSpread(a, p - v3s16(0, 0, 1), light); + lightSpread(a, p - v3s16(0, 1, 0), light); + lightSpread(a, p - v3s16(1, 0, 0), light); +} + + void Mapgen::updateLighting(v3s16 nmin, v3s16 nmax) { + VoxelArea a(nmin - v3s16(1,0,1) * MAP_BLOCKSIZE, + nmax + v3s16(1,0,1) * MAP_BLOCKSIZE); + bool block_is_underground = (water_level >= nmax.Y); + + ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); + //TimeTaker t("updateLighting"); + + // first, send vertical rays of sunshine downward + v3s16 em = vm->m_area.getExtent(); + for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { + for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++) { + // see if we can get a light value from the overtop + u32 i = vm->m_area.index(x, a.MaxEdge.Y + 1, z); + if (vm->m_data[i].getContent() == CONTENT_IGNORE) { + if (block_is_underground) + continue; + } else if ((vm->m_data[i].param1 & 0x0F) != LIGHT_SUN) { + continue; + } + vm->m_area.add_y(em, i, -1); + + for (int y = a.MaxEdge.Y; y >= a.MinEdge.Y; y--) { + MapNode &n = vm->m_data[i]; + if (!ndef->get(n).sunlight_propagates) + break; + n.param1 = LIGHT_SUN; + vm->m_area.add_y(em, i, -1); + } + } + } + + // now spread the sunlight and light up any sources + for (int z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++) { + for (int y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) { + u32 i = vm->m_area.index(a.MinEdge.X, y, z); + for (int x = a.MinEdge.X; x <= a.MaxEdge.X; x++, i++) { + MapNode &n = vm->m_data[i]; + if (n.getContent() == CONTENT_IGNORE || + !ndef->get(n).light_propagates) + continue; + + u8 light_produced = ndef->get(n).light_source & 0x0F; + if (light_produced) + n.param1 = light_produced; + + u8 light = n.param1 & 0x0F; + if (light) { + lightSpread(a, v3s16(x, y, z + 1), light); + lightSpread(a, v3s16(x, y + 1, z ), light); + lightSpread(a, v3s16(x + 1, y, z ), light); + lightSpread(a, v3s16(x, y, z - 1), light); + lightSpread(a, v3s16(x, y - 1, z ), light); + lightSpread(a, v3s16(x - 1, y, z ), light); + } + } + } + } + + //printf("updateLighting: %dms\n", t.stop()); +} + + +void Mapgen::updateLightingOld(v3s16 nmin, v3s16 nmax) { enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT}; VoxelArea a(nmin - v3s16(1,0,1) * MAP_BLOCKSIZE, @@ -84,14 +183,16 @@ void Mapgen::updateLighting(v3s16 nmin, v3s16 nmax) { bool sunlight = !block_is_underground; ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG); + for (int i = 0; i < 2; i++) { enum LightBank bank = banks[i]; - std::set<v3s16> light_sources; - std::map<v3s16, u8> unlight_from; + std::set<v3s16> light_sources; + std::map<v3s16, u8> unlight_from; voxalgo::clearLightAndCollectSources(*vm, a, bank, ndef, light_sources, unlight_from); voxalgo::propagateSunlight(*vm, a, sunlight, light_sources, ndef); + vm->unspreadLight(bank, unlight_from, light_sources, ndef); vm->spreadLight(bank, light_sources, ndef); } diff --git a/src/mapgen.h b/src/mapgen.h index 67ea9fbd4..e5b0b6399 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -46,6 +46,7 @@ class ManualMapVoxelManipulator; class VoxelManipulator; class INodeDefManager; class BlockMakeData; +class VoxelArea; struct MapgenParams { std::string mg_name; @@ -76,7 +77,10 @@ public: INodeDefManager *ndef; void updateLiquid(UniqueQueue<v3s16> *trans_liquid, v3s16 nmin, v3s16 nmax); + void setLighting(v3s16 nmin, v3s16 nmax, u8 light); + void lightSpread(VoxelArea &a, v3s16 p, u8 light); void updateLighting(v3s16 nmin, v3s16 nmax); + void updateLightingOld(v3s16 nmin, v3s16 nmax); virtual void makeChunk(BlockMakeData *data) {}; virtual int getGroundLevelAtPoint(v2s16 p) = 0; |