@@ -231,10 +231,6 @@ void Renderer::modifyTile(TileID id, const void *data) { | |||
RenderChunk Renderer::createChunk( | |||
TileID tiles[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) { | |||
// TODO: Maybe don't do this here? Maybe instead store the buffer and | |||
// upload the texture in the draw method? | |||
// The current approach needs createChunk to be called on the graphics thread. | |||
RenderChunk chunk; | |||
glGenTextures(1, &chunk.tex); | |||
glCheck(); | |||
@@ -243,8 +239,8 @@ RenderChunk Renderer::createChunk( | |||
glBindTexture(GL_TEXTURE_2D, chunk.tex); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |||
glCheck(); | |||
static_assert( |
@@ -3,6 +3,7 @@ | |||
#include <string.h> | |||
#include <stdint.h> | |||
#include <memory> | |||
#include <cygnet/Renderer.h> | |||
#include "util.h" | |||
#include "common.h" | |||
@@ -49,12 +50,12 @@ public: | |||
void setTileID(RelPos pos, Tile::ID id) { | |||
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id; | |||
drawList_.push_back({pos, id}); | |||
changeList_.emplace_back(pos, id); | |||
isModified_ = true; | |||
} | |||
void setTileData(RelPos pos, Tile::ID id) { | |||
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id; | |||
needRender_ = true; | |||
} | |||
uint8_t getLightLevel(RelPos pos) { | |||
@@ -66,14 +67,15 @@ public: | |||
needLightRender_ = true; | |||
} | |||
void compress(); | |||
void generateDone(); | |||
void keepActive(); | |||
void decompress(); | |||
void compress(Cygnet::Renderer &rnd); | |||
void destroy(Cygnet::Renderer &rnd) { rnd.destroyChunk(renderChunk_); } | |||
void draw(const Context &ctx, Cygnet::Renderer &rnd); | |||
TickAction tick(float dt); | |||
bool isActive() { return deactivateTimer_ > 0; } | |||
void keepActive(); | |||
void markModified() { isModified_ = true; } | |||
ChunkPos pos_; | |||
@@ -83,10 +85,11 @@ private: | |||
bool isCompressed() { return compressedSize_ != -1; } | |||
std::unique_ptr<uint8_t[]> data_; | |||
std::vector<std::pair<RelPos, Tile::ID>> drawList_; | |||
std::vector<std::pair<RelPos, Tile::ID>> changeList_; | |||
ssize_t compressedSize_ = -1; // -1 if not compressed, a positive number if compressed | |||
bool needRender_ = false; | |||
Cygnet::RenderChunk renderChunk_; | |||
bool needChunkRender_ = true; | |||
bool needLightRender_ = false; | |||
float deactivateTimer_ = DEACTIVATE_INTERVAL; | |||
bool isModified_ = false; |
@@ -13,7 +13,7 @@ | |||
namespace Swan { | |||
void Chunk::compress() { | |||
void Chunk::compress(Cygnet::Renderer &rnd) { | |||
if (isCompressed()) | |||
return; | |||
@@ -45,7 +45,7 @@ void Chunk::compress() { | |||
warn << "Chunk compression error: " << ret << " (Out of memory?)"; | |||
} | |||
// TODO: Delete renderChunk_ | |||
rnd.destroyChunk(renderChunk_); | |||
} | |||
void Chunk::decompress() { | |||
@@ -64,7 +64,6 @@ void Chunk::decompress() { | |||
} | |||
data_ = std::move(dest); | |||
needRender_ = true; | |||
info | |||
<< "Decompressed chunk " << pos_ << " from " | |||
@@ -72,23 +71,22 @@ void Chunk::decompress() { | |||
<< DATA_SIZE << " bytes."; | |||
compressedSize_ = -1; | |||
// TODO: Create renderChunk_ | |||
needChunkRender_ = true; | |||
} | |||
void Chunk::draw(const Context &ctx, Cygnet::Renderer &rnd) { | |||
if (isCompressed()) | |||
return; | |||
// The world plane is responsible for managing initial renders | |||
if (needRender_) | |||
return; | |||
if (drawList_.size() > 0) { | |||
//renderList(win.renderer_); TODO | |||
drawList_.clear(); | |||
if (needChunkRender_) { | |||
renderChunk_ = rnd.createChunk((Tile::ID *)data_.get()); | |||
} else { | |||
for (auto &change: changeList_) { | |||
rnd.modifyChunk(renderChunk_, change.first, change.second); | |||
} | |||
} | |||
// rnd.drawChunk(renderChunk_, (Vec2)pos_ * Vec2{CHUNK_WIDTH, CHUNK_HEIGHT}); TODO | |||
rnd.drawChunk(renderChunk_, (Vec2)pos_ * Vec2{CHUNK_WIDTH, CHUNK_HEIGHT}); | |||
} | |||
Chunk::TickAction Chunk::tick(float dt) { |
@@ -37,10 +37,10 @@ void Game::draw() { | |||
void Game::update(float dt) { | |||
// Zoom the window using the scroll wheel | |||
cam_.zoom += (float)wasWheelScrolled() * 0.1f * cam_.zoom; | |||
if (cam_.zoom > 3) | |||
cam_.zoom = 3; | |||
else if (cam_.zoom < 0.3) | |||
cam_.zoom = 0.3; | |||
if (cam_.zoom > 1) | |||
cam_.zoom = 1; | |||
else if (cam_.zoom < 0.05) | |||
cam_.zoom = 0.05; | |||
world_->update(dt); | |||
@@ -70,7 +70,7 @@ Chunk &WorldPlane::getChunk(ChunkPos pos) { | |||
} | |||
Chunk &chunk = slowGetChunk(pos); | |||
tickChunks_.push_back({ pos, &chunk }); | |||
tickChunks_.push_back({pos, &chunk}); | |||
return chunk; | |||
} | |||
@@ -97,7 +97,7 @@ Chunk &WorldPlane::slowGetChunk(ChunkPos pos) { | |||
lc.blocks[y * CHUNK_HEIGHT + x] = true; | |||
} | |||
if (tile.lightLevel > 0) { | |||
lc.lightSources[{ x, y }] = tile.lightLevel; | |||
lc.lightSources[{x, y}] = tile.lightLevel; | |||
} | |||
} | |||
} | |||
@@ -123,7 +123,6 @@ void WorldPlane::setTileID(TilePos pos, Tile::ID id) { | |||
Tile &newTile = world_->getTileByID(id); | |||
Tile &oldTile = world_->getTileByID(old); | |||
chunk.setTileID(rp, id); | |||
chunk.markModified(); | |||
if (!oldTile.isSolid && newTile.isSolid) { | |||
lighting_->onSolidBlockAdded(pos); | |||
@@ -275,12 +274,13 @@ void WorldPlane::tick(float dt) { | |||
switch (action) { | |||
case Chunk::TickAction::DEACTIVATE: | |||
info << "Compressing inactive modified chunk " << chunk->pos_; | |||
chunk->compress(); | |||
chunk->compress(world_->game_->renderer_); | |||
iter = activeChunks_.erase(iter); | |||
last = activeChunks_.end(); | |||
break; | |||
case Chunk::TickAction::DELETE: | |||
info << "Deleting inactive unmodified chunk " << chunk->pos_; | |||
chunk->destroy(world_->game_->renderer_); | |||
chunks_.erase(chunk->pos_); | |||
iter = activeChunks_.erase(iter); | |||
last = activeChunks_.end(); |