Add files via upload
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
#include "LightSolver.h"
|
||||
#include "Lightmap.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
|
||||
LightSolver::LightSolver(Chunks* chunks, int channel) : chunks(chunks), channel(channel) {
|
||||
}
|
||||
|
||||
void LightSolver::add(int x, int y, int z, int emission) {
|
||||
if (emission <= 1)
|
||||
return;
|
||||
lightentry entry;
|
||||
entry.x = x;
|
||||
entry.y = y;
|
||||
entry.z = z;
|
||||
entry.light = emission;
|
||||
addqueue.push(entry);
|
||||
|
||||
Chunk* chunk = chunks->getChunkByVoxel(entry.x, entry.y, entry.z);
|
||||
chunk->modified = true;
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, entry.light);
|
||||
}
|
||||
|
||||
void LightSolver::add(int x, int y, int z) {
|
||||
add(x,y,z, chunks->getLight(x,y,z, channel));
|
||||
}
|
||||
|
||||
void LightSolver::remove(int x, int y, int z) {
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x, y, z);
|
||||
if (chunk == nullptr)
|
||||
return;
|
||||
|
||||
int light = chunk->lightmap->get(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel);
|
||||
if (light == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
lightentry entry;
|
||||
entry.x = x;
|
||||
entry.y = y;
|
||||
entry.z = z;
|
||||
entry.light = light;
|
||||
remqueue.push(entry);
|
||||
|
||||
chunk->lightmap->set(entry.x-chunk->x*CHUNK_W, entry.y-chunk->y*CHUNK_H, entry.z-chunk->z*CHUNK_D, channel, 0);
|
||||
}
|
||||
|
||||
void LightSolver::solve(){
|
||||
const int coords[] = {
|
||||
0, 0, 1,
|
||||
0, 0,-1,
|
||||
0, 1, 0,
|
||||
0,-1, 0,
|
||||
1, 0, 0,
|
||||
-1, 0, 0
|
||||
};
|
||||
|
||||
while (!remqueue.empty()){
|
||||
lightentry entry = remqueue.front();
|
||||
remqueue.pop();
|
||||
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
int x = entry.x+coords[i*3+0];
|
||||
int y = entry.y+coords[i*3+1];
|
||||
int z = entry.z+coords[i*3+2];
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x,y,z);
|
||||
if (chunk) {
|
||||
int light = chunks->getLight(x,y,z, channel);
|
||||
if (light != 0 && light == entry.light-1){
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
nentry.z = z;
|
||||
nentry.light = light;
|
||||
remqueue.push(nentry);
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, 0);
|
||||
chunk->modified = true;
|
||||
}
|
||||
else if (light >= entry.light){
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
nentry.z = z;
|
||||
nentry.light = light;
|
||||
addqueue.push(nentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!addqueue.empty()){
|
||||
lightentry entry = addqueue.front();
|
||||
addqueue.pop();
|
||||
|
||||
if (entry.light <= 1)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
int x = entry.x+coords[i*3+0];
|
||||
int y = entry.y+coords[i*3+1];
|
||||
int z = entry.z+coords[i*3+2];
|
||||
Chunk* chunk = chunks->getChunkByVoxel(x,y,z);
|
||||
if (chunk) {
|
||||
int light = chunks->getLight(x,y,z, channel);
|
||||
voxel* v = chunks->get(x,y,z);
|
||||
Block* block = Block::blocks[v->id];
|
||||
if (block->lightPassing && light+2 <= entry.light){
|
||||
chunk->lightmap->set(x-chunk->x*CHUNK_W, y-chunk->y*CHUNK_H, z-chunk->z*CHUNK_D, channel, entry.light-1);
|
||||
chunk->modified = true;
|
||||
lightentry nentry;
|
||||
nentry.x = x;
|
||||
nentry.y = y;
|
||||
nentry.z = z;
|
||||
nentry.light = entry.light-1;
|
||||
addqueue.push(nentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef LIGHTING_LIGHTSOLVER_H_
|
||||
#define LIGHTING_LIGHTSOLVER_H_
|
||||
|
||||
#include <queue>
|
||||
|
||||
class Chunks;
|
||||
|
||||
struct lightentry {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
unsigned char light;
|
||||
};
|
||||
|
||||
class LightSolver {
|
||||
std::queue<lightentry> addqueue;
|
||||
std::queue<lightentry> remqueue;
|
||||
Chunks* chunks;
|
||||
int channel;
|
||||
public:
|
||||
LightSolver(Chunks* chunks, int channel);
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
#endif /* LIGHTING_LIGHTSOLVER_H_ */
|
||||
@@ -0,0 +1,246 @@
|
||||
#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"
|
||||
|
||||
Chunks* Lighting::chunks = nullptr;
|
||||
LightSolver* Lighting::solverR = nullptr;
|
||||
LightSolver* Lighting::solverG = nullptr;
|
||||
LightSolver* Lighting::solverB = nullptr;
|
||||
LightSolver* Lighting::solverS = nullptr;
|
||||
|
||||
int Lighting::initialize(Chunks* chunks){
|
||||
Lighting::chunks = chunks;
|
||||
solverR = new LightSolver(chunks, 0);
|
||||
solverG = new LightSolver(chunks, 1);
|
||||
solverB = new LightSolver(chunks, 2);
|
||||
solverS = new LightSolver(chunks, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Lighting::finalize(){
|
||||
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){
|
||||
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){
|
||||
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->lightPassing)
|
||||
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){
|
||||
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->lightPassing)
|
||||
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 {
|
||||
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->lightPassing)
|
||||
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;
|
||||
solverR->add(gx,gy,gz);
|
||||
solverG->add(gx,gy,gz);
|
||||
solverB->add(gx,gy,gz);
|
||||
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)
|
||||
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->lightPassing){
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef LIGHTING_LIGHTING_H_
|
||||
#define LIGHTING_LIGHTING_H_
|
||||
|
||||
class Chunks;
|
||||
class LightSolver;
|
||||
|
||||
class Lighting {
|
||||
static Chunks* chunks;
|
||||
static LightSolver* solverR;
|
||||
static LightSolver* solverG;
|
||||
static LightSolver* solverB;
|
||||
static LightSolver* solverS;
|
||||
public:
|
||||
static int initialize(Chunks* chunks);
|
||||
static void finalize();
|
||||
|
||||
static void clear();
|
||||
static void onChunkLoaded(int cx, int cy, int cz);
|
||||
static void onBlockSet(int x, int y, int z, int id);
|
||||
};
|
||||
|
||||
#endif /* LIGHTING_LIGHTING_H_ */
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "Lightmap.h"
|
||||
|
||||
Lightmap::Lightmap(){
|
||||
map = new unsigned short[CHUNK_VOL];
|
||||
for (unsigned int i = 0; i < CHUNK_VOL; i++){
|
||||
map[i] = 0x0000;
|
||||
}
|
||||
}
|
||||
|
||||
Lightmap::~Lightmap(){
|
||||
delete[] map;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef LIGHTING_LIGHTMAP_H_
|
||||
#define LIGHTING_LIGHTMAP_H_
|
||||
|
||||
#include "../voxels/Chunk.h"
|
||||
|
||||
class Lightmap {
|
||||
public:
|
||||
unsigned short* map;
|
||||
Lightmap();
|
||||
~Lightmap();
|
||||
|
||||
inline unsigned char get(int x, int y, int z, int channel){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> (channel << 2)) & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getR(int x, int y, int z){
|
||||
return map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getG(int x, int y, int z){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 4) & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getB(int x, int y, int z){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 8) & 0xF;
|
||||
}
|
||||
|
||||
inline unsigned char getS(int x, int y, int z){
|
||||
return (map[y*CHUNK_D*CHUNK_W+z*CHUNK_W+x] >> 12) & 0xF;
|
||||
}
|
||||
|
||||
inline void setR(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0xFFF0) | value;
|
||||
}
|
||||
|
||||
inline void setG(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0xFF0F) | (value << 4);
|
||||
}
|
||||
|
||||
inline void setB(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0xF0FF) | (value << 8);
|
||||
}
|
||||
|
||||
inline void setS(int x, int y, int z, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & 0x0FFF) | (value << 12);
|
||||
}
|
||||
|
||||
inline void set(int x, int y, int z, int channel, int value){
|
||||
const int index = y*CHUNK_D*CHUNK_W+z*CHUNK_W+x;
|
||||
map[index] = (map[index] & (0xFFFF & (~(0xF << (channel*4))))) | (value << (channel << 2));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* LIGHTING_LIGHTMAP_H_ */
|
||||
Reference in New Issue
Block a user