]> git.localhorst.tv Git - blank.git/blobdiff - src/world/chunk.cpp
"streamlined" model/VAO handling
[blank.git] / src / world / chunk.cpp
index 75f9c4f424c28d8babc77ef9322921a7db96a899..190fe3d7b9e4c4aa25d4fbaf6745845c97b0565b 100644 (file)
@@ -65,9 +65,13 @@ struct SetNode {
        int Get() const noexcept { return chunk->GetLight(pos); }
        void Set(int level) noexcept { chunk->SetLight(pos, level); }
 
+       const BlockType &GetType() const noexcept { return chunk->Type(Chunk::ToIndex(pos)); }
+
        bool HasNext(Block::Face face) noexcept {
+               const BlockType &type = GetType();
+               if (type.block_light && !type.luminosity) return false;
                const BlockLookup next(chunk, pos, face);
-               return next && !next.GetType().block_light;
+               return next;
        }
        SetNode GetNext(Block::Face face) noexcept {
                const BlockLookup next(chunk, pos, face);
@@ -295,23 +299,10 @@ void Chunk::SetNeighbor(Chunk &other) noexcept {
 }
 
 void Chunk::ClearNeighbors() noexcept {
-       for (int i = 0; i < Block::FACE_COUNT; ++i) {
-               neighbor[i] = nullptr;
-       }
-}
-
-void Chunk::Unlink() noexcept {
        for (int face = 0; face < Block::FACE_COUNT; ++face) {
                if (neighbor[face]) {
                        neighbor[face]->neighbor[Block::Opposite(Block::Face(face))] = nullptr;
-               }
-       }
-}
-
-void Chunk::Relink() noexcept {
-       for (int face = 0; face < Block::FACE_COUNT; ++face) {
-               if (neighbor[face]) {
-                       neighbor[face]->neighbor[Block::Opposite(Block::Face(face))] = this;
+                       neighbor[face] = nullptr;
                }
        }
 }
@@ -328,7 +319,7 @@ int Chunk::GetLight(int index) const noexcept {
        return light[index];
 }
 
-float Chunk::GetVertexLight(const Pos &pos, const BlockModel::Position &vtx, const Model::Normal &norm) const noexcept {
+float Chunk::GetVertexLight(const Pos &pos, const BlockModel::Position &vtx, const EntityModel::Normal &norm) const noexcept {
        int index = ToIndex(pos);
        float light = GetLight(index);
 
@@ -760,8 +751,15 @@ void ChunkLoader::Insert(Chunk &chunk) noexcept {
        }
 }
 
-void ChunkLoader::Remove(Chunk &chunk) noexcept {
-       chunk.Unlink();
+std::list<Chunk>::iterator ChunkLoader::Remove(std::list<Chunk>::iterator chunk) noexcept {
+       // fetch next entry while chunk's still in the list
+       std::list<Chunk>::iterator next = chunk;
+       ++next;
+       // unlink neighbors so they won't reference a dead chunk
+       chunk->ClearNeighbors();
+       // and move it from loaded to free list
+       to_free.splice(to_free.end(), loaded, chunk);
+       return next;
 }
 
 Chunk *ChunkLoader::Loaded(const Chunk::Pos &pos) noexcept {
@@ -818,10 +816,7 @@ void ChunkLoader::Rebase(const Chunk::Pos &new_base) {
        // unload far away chunks
        for (auto iter(loaded.begin()), end(loaded.end()); iter != end;) {
                if (OutOfRange(*iter)) {
-                       auto saved = iter;
-                       Remove(*saved);
-                       ++iter;
-                       to_free.splice(to_free.end(), loaded, saved);
+                       iter = Remove(iter);
                } else {
                        ++iter;
                }
@@ -844,27 +839,35 @@ void ChunkLoader::GenerateSurrounding(const Chunk::Pos &pos) {
 }
 
 void ChunkLoader::Update(int dt) {
+       // check if a chunk generation is scheduled for this frame
+       // and if there's a chunk waiting to be generated
        gen_timer.Update(dt);
        if (!gen_timer.Hit() || to_generate.empty()) {
                return;
        }
 
+       // take position of next chunk in queue
        Chunk::Pos pos(to_generate.front());
        to_generate.pop_front();
 
+       // look if the same chunk was already generated and still lingering
        for (auto iter(to_free.begin()), end(to_free.end()); iter != end; ++iter) {
                if (iter->Position() == pos) {
-                       iter->Relink();
                        loaded.splice(loaded.end(), to_free, iter);
+                       Insert(loaded.back());
+                       return;
                }
        }
 
+       // if the free list is empty, allocate a new chunk
+       // otherwise clear an unused one
        if (to_free.empty()) {
                loaded.emplace_back(reg);
        } else {
                to_free.front().ClearNeighbors();
                loaded.splice(loaded.end(), to_free, to_free.begin());
        }
+
        Chunk &chunk = loaded.back();
        chunk.Position(pos);
        gen(chunk);