aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkwolekr <kwolekr@minetest.net>2013-03-15 22:43:35 -0400
committerkwolekr <kwolekr@minetest.net>2013-03-15 23:04:50 -0400
commit1f1ad9fd23b07a1c1b5477ee0dbf2c4fdaabccef (patch)
treecb91947db58be0835c2f0330b876f0635bd24ab1 /src
parentf5ab056b388b856a70bca7a028b58a258532716f (diff)
downloadminetest-1f1ad9fd23b07a1c1b5477ee0dbf2c4fdaabccef.tar.gz
minetest-1f1ad9fd23b07a1c1b5477ee0dbf2c4fdaabccef.tar.bz2
minetest-1f1ad9fd23b07a1c1b5477ee0dbf2c4fdaabccef.zip
Optimize Mapgen::updateLighting(), add setLighting()
Diffstat (limited to 'src')
-rw-r--r--src/mapgen.cpp117
-rw-r--r--src/mapgen.h4
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;