diff --git a/src/lighting/LightSolver.cpp b/src/lighting/LightSolver.cpp index b6091fdc5..f43b4d487 100644 --- a/src/lighting/LightSolver.cpp +++ b/src/lighting/LightSolver.cpp @@ -1,6 +1,3 @@ -#include -#include - #include "LightSolver.hpp" #include "Lightmap.hpp" #include "content/Content.hpp" @@ -9,6 +6,8 @@ #include "voxels/voxel.hpp" #include "voxels/Block.hpp" +#include + LightSolver::LightSolver(const ContentIndices& contentIds, Chunks& chunks, int channel) : blockDefs(contentIds.blocks.getDefs()), chunks(chunks), @@ -55,7 +54,7 @@ void LightSolver::remove(int x, int y, int z) { lightmap.set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, 0); } -void LightSolver::solve() { +void LightSolver::solve(Chunk* prevailingChunk) { const int coords[] = { 0, 0, 1, 0, 0,-1, @@ -75,10 +74,16 @@ void LightSolver::solve() { int y = entry.y+coords[imul3+1]; int z = entry.z+coords[imul3+2]; - Chunk* chunk = chunks.getChunkByVoxel(x,y,z); - if (chunk == nullptr) { + Chunk* chunk = prevailingChunk; + if (chunk == nullptr || !chunk->isBlockInside(x, z)) { + chunk = chunks.getChunkByVoxel(x,y,z); + if (chunk == nullptr) { + continue; + } + } else if (y < 0 || y >= CHUNK_H) { continue; } + int lx = x - chunk->x * CHUNK_W; int lz = z - chunk->z * CHUNK_D; chunk->flags.modified = true; @@ -116,10 +121,16 @@ void LightSolver::solve() { int y = entry.y+coords[imul3+1]; int z = entry.z+coords[imul3+2]; - Chunk* chunk = chunks.getChunkByVoxel(x,y,z); - if (chunk == nullptr) { + Chunk* chunk = prevailingChunk; + if (chunk == nullptr || !chunk->isBlockInside(x, z)) { + chunk = chunks.getChunkByVoxel(x,y,z); + if (chunk == nullptr) { + continue; + } + } else if (y < 0 || y >= CHUNK_H) { continue; } + assert(chunk->lightmap != nullptr); auto& lightmap = *chunk->lightmap; int lx = x - chunk->x * CHUNK_W; diff --git a/src/lighting/LightSolver.hpp b/src/lighting/LightSolver.hpp index 1e36a0e1d..31c33a804 100644 --- a/src/lighting/LightSolver.hpp +++ b/src/lighting/LightSolver.hpp @@ -2,6 +2,7 @@ #include "util/array_queue.hpp" +class Chunk; class Chunks; class ContentIndices; class Block; @@ -25,5 +26,5 @@ public: void add(int x, int y, int z); void add(int x, int y, int z, int emission); void remove(int x, int y, int z); - void solve(); + void solve(Chunk* prevailingChunk = nullptr); }; diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index 9101c72ac..8f90540bb 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -167,10 +167,10 @@ void Lighting::onChunkLoaded(int cx, int cz, bool expand) { } } } - solverR.solve(); - solverG.solve(); - solverB.solve(); - solverS.solve(); + solverR.solve(chunk); + solverG.solve(chunk); + solverB.solve(chunk); + solverS.solve(chunk); } void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ @@ -180,9 +180,10 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ solverB->remove(x,y,z); if (id == 0){ - solverR->solve(); - solverG->solve(); - solverB->solve(); + auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z}); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); if (chunks.getLight(x,y+1,z, 3) == 0xF){ for (int i = y; i >= 0; i--){ voxel* vox = chunks.get(x,i,z); @@ -197,11 +198,12 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ solverR->add(x-1,y,z); solverG->add(x-1,y,z); solverB->add(x-1,y,z); solverS->add(x-1,y,z); solverR->add(x,y,z+1); solverG->add(x,y,z+1); solverB->add(x,y,z+1); solverS->add(x,y,z+1); solverR->add(x,y,z-1); solverG->add(x,y,z-1); solverB->add(x,y,z-1); solverS->add(x,y,z-1); - solverR->solve(); - solverG->solve(); - solverB->solve(); - solverS->solve(); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); + solverS->solve(chunk); } else { + auto chunk = chunks.getChunkByVoxel(glm::ivec3{x, y, z}); if (!block.skyLightPassing){ solverS->remove(x,y,z); for (int i = y-1; i >= 0; i--){ @@ -210,19 +212,19 @@ void Lighting::onBlockSet(int x, int y, int z, blockid_t id){ break; } } - solverS->solve(); + solverS->solve(chunk); } - solverR->solve(); - solverG->solve(); - solverB->solve(); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); if (block.emission[0] || block.emission[1] || block.emission[2]){ solverR->add(x,y,z,block.emission[0]); solverG->add(x,y,z,block.emission[1]); solverB->add(x,y,z,block.emission[2]); - solverR->solve(); - solverG->solve(); - solverB->solve(); + solverR->solve(chunk); + solverG->solve(chunk); + solverB->solve(chunk); } } } diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 5d45629ea..5377df020 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -83,4 +83,10 @@ public: glm::vec3((x + 1) * CHUNK_W, INFINITY, (z + 1) * CHUNK_D) ); } + + bool isBlockInside(int x, int z) const { + x -= this->x * CHUNK_W; + z -= this->z * CHUNK_D; + return x >= 0 && z >= 0 && x < CHUNK_W && z < CHUNK_D; + } };