243 lines
6.8 KiB
C++
243 lines
6.8 KiB
C++
#include "Lighting.h"
|
|
#include "LightSolver.h"
|
|
#include "Lightmap.h"
|
|
#include "../voxels/Chunks.h"
|
|
#include "../voxels/Chunk.h"
|
|
#include "../voxels/voxel.h"
|
|
#include "../voxels/Block.h"
|
|
|
|
Lighting::Lighting(Chunks* chunks){
|
|
this->chunks = chunks;
|
|
solverR = new LightSolver(chunks, 0);
|
|
solverG = new LightSolver(chunks, 1);
|
|
solverB = new LightSolver(chunks, 2);
|
|
solverS = new LightSolver(chunks, 3);
|
|
}
|
|
|
|
Lighting::~Lighting(){
|
|
delete solverR, solverG, solverB, solverS;
|
|
}
|
|
|
|
void Lighting::clear(){
|
|
for (unsigned int index = 0; index < chunks->volume; index++){
|
|
Chunk* chunk = chunks->chunks[index];
|
|
if (chunk == nullptr)
|
|
continue;
|
|
Lightmap* lightmap = chunk->lightmap;
|
|
for (int i = 0; i < CHUNK_VOL; i++){
|
|
lightmap->map[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Lighting::onChunkLoaded(int cx, int cy, int cz, bool sky){
|
|
Chunk* chunk = chunks->getChunk(cx, cy, cz);
|
|
Chunk* chunkUpper = chunks->getChunk(cx, cy+1, cz);
|
|
Chunk* chunkLower = chunks->getChunk(cx, cy-1, cz);
|
|
if (chunkLower && sky){
|
|
for (int z = 0; z < CHUNK_D; z++){
|
|
for (int x = 0; x < CHUNK_W; x++){
|
|
int gx = x + cx * CHUNK_W;
|
|
int gy = cy * CHUNK_H;
|
|
int gz = z + cz * CHUNK_D;
|
|
|
|
int light = chunk->lightmap->getS(x,0,z);
|
|
int ncy = cy-1;
|
|
if (light < 15){
|
|
Chunk* current = chunkLower;
|
|
if (chunkLower->lightmap->getS(x,15,z) == 0)
|
|
continue;
|
|
for (int y = 15;;y--){
|
|
if (y < 0){
|
|
ncy--;
|
|
y += CHUNK_H;
|
|
}
|
|
if (ncy != current->y)
|
|
current = chunks->getChunk(cx,ncy,cz);
|
|
if (!current)
|
|
break;
|
|
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
|
Block* block = Block::blocks[vox->id];
|
|
if (!block->skyLightPassing)
|
|
break;
|
|
//current->lightmap->setS(x,y,z, 0);
|
|
current->modified = true;
|
|
solverS->remove(gx,y+ncy*CHUNK_H,gz);
|
|
current->lightmap->setS(x,y,z, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (chunkUpper && sky){
|
|
for (int z = 0; z < CHUNK_D; z++){
|
|
for (int x = 0; x < CHUNK_W; x++){
|
|
int gx = x + cx * CHUNK_W;
|
|
int gy = cy * CHUNK_H;
|
|
int gz = z + cz * CHUNK_D;
|
|
int ncy = cy;
|
|
|
|
int light = chunkUpper->lightmap->getS(x,0,z);
|
|
|
|
Chunk* current = chunk;
|
|
if (light == 15){
|
|
for (int y = CHUNK_H-1;;y--){
|
|
if (y < 0){
|
|
ncy--;
|
|
y += CHUNK_H;
|
|
}
|
|
if (ncy != current->y)
|
|
current = chunks->getChunk(cx,ncy,cz);
|
|
if (!current)
|
|
break;
|
|
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
|
Block* block = Block::blocks[vox->id];
|
|
if (!block->skyLightPassing)
|
|
break;
|
|
current->lightmap->setS(x,y,z, 15);
|
|
current->modified = true;
|
|
solverS->add(gx,y+ncy*CHUNK_H,gz);
|
|
}
|
|
} else if (light){
|
|
solverS->add(gx,gy+CHUNK_H,gz);
|
|
}
|
|
}
|
|
}
|
|
} else if (sky){
|
|
for (int z = 0; z < CHUNK_D; z++){
|
|
for (int x = 0; x < CHUNK_W; x++){
|
|
int gx = x + cx * CHUNK_W;
|
|
int gz = z + cz * CHUNK_D;
|
|
int ncy = cy;
|
|
|
|
Chunk* current = chunk;
|
|
for (int y = CHUNK_H-1;;y--){
|
|
if (y < 0){
|
|
ncy--;
|
|
y += CHUNK_H;
|
|
}
|
|
if (ncy != current->y)
|
|
current = chunks->getChunk(cx,ncy,cz);
|
|
if (!current)
|
|
break;
|
|
voxel* vox = &(current->voxels[(y * CHUNK_D + z) * CHUNK_W + x]);//chunks->get(gx,gy+y,gz);
|
|
Block* block = Block::blocks[vox->id];
|
|
if (!block->skyLightPassing)
|
|
break;
|
|
current->lightmap->setS(x,y,z, 15);
|
|
current->modified = true;
|
|
solverS->add(gx,y+ncy*CHUNK_H,gz);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//std::cout << "DONE" << std::endl;
|
|
for (unsigned int y = 0; y < CHUNK_H; y++){
|
|
for (unsigned int z = 0; z < CHUNK_D; z++){
|
|
for (unsigned int x = 0; x < CHUNK_W; x++){
|
|
voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x];
|
|
Block* block = Block::blocks[vox.id];
|
|
if (block->emission[0] || block->emission[1] || block->emission[2]){
|
|
int gx = x + cx * CHUNK_W;
|
|
int gy = y + cy * CHUNK_H;
|
|
int gz = z + cz * CHUNK_D;
|
|
solverR->add(gx,gy,gz,block->emission[0]);
|
|
solverG->add(gx,gy,gz,block->emission[1]);
|
|
solverB->add(gx,gy,gz,block->emission[2]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int y = -1; y <= CHUNK_H; y++){
|
|
for (int z = -1; z <= CHUNK_D; z++){
|
|
for (int x = -1; x <= CHUNK_W; x++){
|
|
if (!(x == -1 || x == CHUNK_W || y == -1 || y == CHUNK_H || z == -1 || z == CHUNK_D))
|
|
continue;
|
|
int gx = x + cx * CHUNK_W;
|
|
int gy = y + cy * CHUNK_H;
|
|
int gz = z + cz * CHUNK_D;
|
|
if (chunks->getLight(x,y,z)){
|
|
solverR->add(gx,gy,gz);
|
|
solverG->add(gx,gy,gz);
|
|
solverB->add(gx,gy,gz);
|
|
if (sky)
|
|
solverS->add(gx,gy,gz);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
solverR->solve();
|
|
solverG->solve();
|
|
solverB->solve();
|
|
solverS->solve();
|
|
|
|
Chunk* other;
|
|
other = chunks->getChunk(cx-1,cy,cz); if (other) other->modified = true;
|
|
other = chunks->getChunk(cx+1,cy,cz); if (other) other->modified = true;
|
|
other = chunks->getChunk(cx,cy-1,cz); if (other) other->modified = true;
|
|
other = chunks->getChunk(cx,cy+1,cz); if (other) other->modified = true;
|
|
other = chunks->getChunk(cx,cy,cz-1); if (other) other->modified = true;
|
|
other = chunks->getChunk(cx,cy,cz+1); if (other) other->modified = true;
|
|
}
|
|
|
|
void Lighting::onBlockSet(int x, int y, int z, int id){
|
|
Block* block = Block::blocks[id];
|
|
if (id == 0){
|
|
solverR->remove(x,y,z);
|
|
solverG->remove(x,y,z);
|
|
solverB->remove(x,y,z);
|
|
|
|
solverR->solve();
|
|
solverG->solve();
|
|
solverB->solve();
|
|
|
|
if (chunks->getLight(x,y+1,z, 3) == 0xF){
|
|
for (int i = y; i >= 0; i--){
|
|
voxel* vox = chunks->get(x,i,z);
|
|
if (vox == nullptr || vox->id != 0 && Block::blocks[id]->skyLightPassing)
|
|
break;
|
|
solverS->add(x,i,z, 0xF);
|
|
}
|
|
}
|
|
|
|
solverR->add(x,y+1,z); solverG->add(x,y+1,z); solverB->add(x,y+1,z); solverS->add(x,y+1,z);
|
|
solverR->add(x,y-1,z); solverG->add(x,y-1,z); solverB->add(x,y-1,z); solverS->add(x,y-1,z);
|
|
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-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();
|
|
} else {
|
|
solverR->remove(x,y,z);
|
|
solverG->remove(x,y,z);
|
|
solverB->remove(x,y,z);
|
|
if (!block->skyLightPassing){
|
|
solverS->remove(x,y,z);
|
|
for (int i = y-1; i >= 0; i--){
|
|
solverS->remove(x,i,z);
|
|
if (i == 0 || chunks->get(x,i-1,z)->id != 0){
|
|
break;
|
|
}
|
|
}
|
|
solverS->solve();
|
|
}
|
|
solverR->solve();
|
|
solverG->solve();
|
|
solverB->solve();
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|