@@ -14,7 +14,7 @@ namespace Swan { | |||
struct NewLightChunk { | |||
std::bitset<CHUNK_WIDTH * CHUNK_HEIGHT> blocks; | |||
std::map<std::pair<int, int>, uint8_t> light_sources; | |||
std::map<std::pair<int, int>, int> light_sources; | |||
}; | |||
struct LightChunk { | |||
@@ -25,7 +25,7 @@ struct LightChunk { | |||
std::bitset<CHUNK_WIDTH * CHUNK_HEIGHT> blocks; | |||
uint8_t light_levels[CHUNK_WIDTH * CHUNK_HEIGHT] = { 0 }; | |||
uint8_t blocks_line[CHUNK_WIDTH] = { 0 }; | |||
std::map<std::pair<int, int>, uint8_t> light_sources; | |||
std::map<std::pair<int, int>, int> light_sources; | |||
bool was_updated = false; | |||
}; | |||
@@ -42,8 +42,8 @@ public: | |||
void onSolidBlockAdded(TilePos pos); | |||
void onSolidBlockRemoved(TilePos pos); | |||
void onLightAdded(TilePos pos, uint8_t level); | |||
void onLightRemoved(TilePos pos, uint8_t level); | |||
void onLightAdded(TilePos pos, int level); | |||
void onLightRemoved(TilePos pos, int level); | |||
void onChunkAdded(ChunkPos pos, NewLightChunk &&chunk); | |||
void onChunkRemoved(ChunkPos pos); | |||
@@ -56,7 +56,7 @@ private: | |||
TilePos pos; | |||
union { | |||
size_t num; | |||
int num; | |||
}; | |||
}; | |||
@@ -65,7 +65,7 @@ private: | |||
int recalcTile( | |||
LightChunk &chunk, ChunkPos cpos, Vec2i rpos, TilePos base, | |||
std::vector<std::pair<TilePos, uint8_t>> &lights); | |||
std::vector<std::pair<TilePos, int>> &lights); | |||
void processUpdatedChunk(LightChunk &chunk, ChunkPos cpos); | |||
void processEvent(const Event &event, std::vector<NewLightChunk> &newChunks); | |||
void run(); | |||
@@ -97,13 +97,13 @@ inline void LightServer::onSolidBlockRemoved(TilePos pos) { | |||
cond_.notify_one(); | |||
} | |||
inline void LightServer::onLightAdded(TilePos pos, uint8_t level) { | |||
inline void LightServer::onLightAdded(TilePos pos, int level) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
buffers_[buffer_].push_back({ Event::Tag::LIGHT_ADDED, pos, { .num = level } }); | |||
cond_.notify_one(); | |||
} | |||
inline void LightServer::onLightRemoved(TilePos pos, uint8_t level) { | |||
inline void LightServer::onLightRemoved(TilePos pos, int level) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
buffers_[buffer_].push_back({ Event::Tag::LIGHT_REMOVED, pos, { .num = level } }); | |||
cond_.notify_one(); | |||
@@ -112,7 +112,7 @@ inline void LightServer::onLightRemoved(TilePos pos, uint8_t level) { | |||
inline void LightServer::onChunkAdded(Vec2i pos, NewLightChunk &&chunk) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
buffers_[buffer_].push_back({ Event::Tag::CHUNK_ADDED, pos, | |||
{ .num = new_chunk_buffers_[buffer_].size() } }); | |||
{ .num = (int)new_chunk_buffers_[buffer_].size() } }); | |||
new_chunk_buffers_[buffer_].push_back(std::move(chunk)); | |||
cond_.notify_one(); | |||
} |
@@ -76,6 +76,9 @@ public: | |||
void debugBox(TilePos pos); | |||
void addLight(TilePos pos, uint8_t level); | |||
void removeLight(TilePos pos, uint8_t level); | |||
// LightingCallback implementation | |||
void onLightChunkUpdated(const LightChunk &chunk, Vec2i pos) final; | |||
@@ -85,9 +88,6 @@ public: | |||
std::mutex mut_; | |||
private: | |||
void addLight(TilePos pos, uint8_t level); | |||
void removeLight(TilePos pos, uint8_t level); | |||
std::unique_ptr<LightServer> lighting_; | |||
std::map<std::pair<int, int>, Chunk> chunks_; |
@@ -104,6 +104,9 @@ void LightServer::processEvent(const Event &evt, std::vector<NewLightChunk> &new | |||
case Event::Tag::LIGHT_REMOVED: | |||
info << cpos << ": Remove " << evt.num << " light to " << rpos; | |||
ch->light_sources[rpos] -= evt.num; | |||
if (ch->light_sources[rpos] == 0) { | |||
ch->light_sources.erase(rpos); | |||
} | |||
break; | |||
// These were handled earlier | |||
@@ -115,7 +118,7 @@ void LightServer::processEvent(const Event &evt, std::vector<NewLightChunk> &new | |||
int LightServer::recalcTile( | |||
LightChunk &chunk, ChunkPos cpos, Vec2i rpos, TilePos base, | |||
std::vector<std::pair<TilePos, uint8_t>> &lights) { | |||
std::vector<std::pair<TilePos, int>> &lights) { | |||
TilePos pos = rpos + base; | |||
constexpr int accuracy = 4; | |||
@@ -133,8 +136,6 @@ int LightServer::recalcTile( | |||
currtile = t; | |||
}; | |||
proceed(); | |||
bool hit = false; | |||
while ((currpos - from).squareLength() <= diff.squareLength()) { | |||
if (tileIsSolid(currtile)) { | |||
@@ -162,21 +163,35 @@ int LightServer::recalcTile( | |||
float dist = ((Vec2)(lightpos - pos)).length(); | |||
int light = level - (int)dist; | |||
int hit = | |||
if (!tileIsSolid(pos)) { | |||
bool hit = raycast( | |||
Vec2(pos.x + 0.5, pos.y + 0.5), | |||
Vec2(lightpos.x + 0.5, lightpos.y + 0.5)); | |||
if (!hit) { | |||
acc += light; | |||
} | |||
continue; | |||
} | |||
bool blocked = | |||
raycast( | |||
Vec2(pos.x + 0.3, pos.y + 0.3), | |||
Vec2(lightpos.x + 0.3, lightpos.y + 0.3)) + | |||
Vec2(pos.x + 0.5, pos.y - 0.1), | |||
Vec2(lightpos.x + 0.5, lightpos.y + 0.5)) && | |||
raycast( | |||
Vec2(pos.x + 0.7, pos.y + 0.3), | |||
Vec2(lightpos.x + 0.7, lightpos.y + 0.3)) + | |||
Vec2(pos.x + 0.5, pos.y + 1.1), | |||
Vec2(lightpos.x + 0.5, lightpos.y + 0.5)) && | |||
raycast( | |||
Vec2(pos.x + 0.3, pos.y + 0.7), | |||
Vec2(lightpos.x + 0.3, lightpos.y + 0.7)) + | |||
Vec2(pos.x - 0.1, pos.y + 0.5), | |||
Vec2(lightpos.x + 0.5, lightpos.y + 0.5)) && | |||
raycast( | |||
Vec2(pos.x + 0.7, pos.y + 0.7), | |||
Vec2(lightpos.x + 0.7, lightpos.y + 0.7)); | |||
Vec2(pos.x + 1.1, pos.y + 0.5), | |||
Vec2(lightpos.x + 0.5, lightpos.y + 0.5)); | |||
if (!blocked) { | |||
acc += light; | |||
} | |||
acc += (light * (4 - hit)) / 4; | |||
if (acc >= 255) { | |||
return 255; | |||
} | |||
@@ -188,7 +203,7 @@ int LightServer::recalcTile( | |||
void LightServer::processUpdatedChunk(LightChunk &chunk, ChunkPos cpos) { | |||
auto start = std::chrono::steady_clock::now(); | |||
TilePos base = cpos * Vec2i(CHUNK_WIDTH, CHUNK_HEIGHT); | |||
std::vector<std::pair<TilePos, uint8_t>> lights; | |||
std::vector<std::pair<TilePos, int>> lights; | |||
for (auto &[pos, level]: chunk.light_sources) { | |||
lights.emplace_back(Vec2i(pos) + base, level); |
@@ -218,7 +218,6 @@ void WorldPlane::draw(Win &win) { | |||
// Just init one chunk per frame | |||
if (chunk_init_list_.size() > 0) { | |||
Chunk *chunk = chunk_init_list_.front(); | |||
info << "render chunk " << chunk->pos_; | |||
chunk_init_list_.pop_front(); | |||
chunk->render(ctx, win.renderer_); | |||
} | |||
@@ -295,18 +294,20 @@ void WorldPlane::debugBox(TilePos pos) { | |||
debug_boxes_.push_back(pos); | |||
} | |||
void WorldPlane::onLightChunkUpdated(const LightChunk &chunk, ChunkPos pos) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
Chunk &realChunk = getChunk(pos); | |||
realChunk.setLightData(chunk.light_levels); | |||
} | |||
void WorldPlane::addLight(TilePos pos, uint8_t level) { | |||
getChunk(chunkPos(pos)); | |||
lighting_->onLightAdded(pos, level); | |||
} | |||
void WorldPlane::removeLight(TilePos pos, uint8_t level) { | |||
getChunk(chunkPos(pos)); | |||
lighting_->onLightRemoved(pos, level); | |||
} | |||
void WorldPlane::onLightChunkUpdated(const LightChunk &chunk, ChunkPos pos) { | |||
std::lock_guard<std::mutex> lock(mut_); | |||
Chunk &realChunk = getChunk(pos); | |||
realChunk.setLightData(chunk.light_levels); | |||
} | |||
} |