X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fchunk.cpp;h=23d5a13c260e8dfdefab8e5ec3f444a8a537967f;hb=35c09fc00094a3d390732fd533b2bd03413d90c7;hp=5162952347b492c8578bf28da291555a37059533;hpb=38abfe4f5342f20b56052ac3090694eabf028d16;p=blank.git diff --git a/src/chunk.cpp b/src/chunk.cpp index 5162952..23d5a13 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -2,6 +2,7 @@ #include "generator.hpp" +#include #include #include #include @@ -11,9 +12,9 @@ namespace blank { Chunk::Chunk(const BlockTypeRegistry &types) : types(&types) -, neighbor{ 0, 0, 0, 0, 0, 0 } -, blocks() -, light() +, neighbor{0} +, blocks{} +, light{0} , model() , position(0, 0, 0) , dirty(false) { @@ -22,23 +23,19 @@ Chunk::Chunk(const BlockTypeRegistry &types) Chunk::Chunk(Chunk &&other) : types(other.types) -, blocks(std::move(other.blocks)) -, light(std::move(other.light)) , model(std::move(other.model)) , position(other.position) , dirty(other.dirty) { - for (size_t i = 0; i < Block::FACE_COUNT; ++i) { - neighbor[i] = other.neighbor[i]; - } + std::copy(other.neighbor, other.neighbor + sizeof(neighbor), neighbor); + std::copy(other.blocks, other.blocks + sizeof(blocks), blocks); + std::copy(other.light, other.light + sizeof(light), light); } Chunk &Chunk::operator =(Chunk &&other) { types = other.types; - for (size_t i = 0; i < Block::FACE_COUNT; ++i) { - neighbor[i] = other.neighbor[i]; - } - blocks = std::move(other.blocks); - light = std::move(other.light); + std::copy(other.neighbor, other.neighbor + sizeof(neighbor), neighbor); + std::copy(other.blocks, other.blocks + sizeof(blocks), blocks); + std::copy(other.light, other.light + sizeof(light), light); model = std::move(other.model); position = other.position; dirty = other.dirty; @@ -61,11 +58,11 @@ struct SetNode { bool HasNext(Block::Face face) { const BlockLookup next(chunk, pos, face); - return next.result && !next.chunk->Type(*next.result).block_light; + return next && !next.GetType().block_light; } SetNode GetNext(Block::Face face) { const BlockLookup next(chunk, pos, face); - return SetNode(next.chunk, next.pos); + return SetNode(&next.GetChunk(), next.GetBlockPos()); } }; @@ -84,7 +81,7 @@ struct UnsetNode bool HasNext(Block::Face face) { const BlockLookup next(chunk, pos, face); - return next.result; + return next; } UnsetNode GetNext(Block::Face face) { return UnsetNode(SetNode::GetNext(face)); } @@ -166,18 +163,9 @@ void Chunk::SetBlock(int index, const Block &block) { // obstacle removed int level = 0; for (int face = 0; face < Block::FACE_COUNT; ++face) { - Pos next_pos(ToPos(index) + Block::FaceNormal(Block::Face(face))); - int next_level = 0; - if (InBounds(next_pos)) { - next_level = GetLight(next_pos); - } else { - if (HasNeighbor(Block::Face(face))) { - next_pos -= (Block::FaceNormal(Block::Face(face)) * Chunk::Extent()); - next_level = GetNeighbor(Block::Face(face)).GetLight(next_pos); - } - } - if (level < next_level) { - level = next_level; + BlockLookup next_block(this, ToPos(index), Block::Face(face)); + if (next_block) { + level = std::min(level, next_block.GetLight()); } } if (level > 1) { @@ -188,17 +176,6 @@ void Chunk::SetBlock(int index, const Block &block) { } } -const Block *Chunk::FindNext(const Pos &pos, Block::Face face) const { - Pos next_pos(pos + Block::FaceNormal(face)); - if (InBounds(next_pos)) { - return &BlockAt(pos + Block::FaceNormal(face)); - } else if (HasNeighbor(face)) { - return &GetNeighbor(face).BlockAt(next_pos - (Block::FaceNormal(face) * Extent())); - } else { - return nullptr; - } -} - void Chunk::SetNeighbor(Chunk &other) { if (other.position == position + Pos(-1, 0, 0)) { if (neighbor[Block::FACE_LEFT] != &other) { @@ -318,44 +295,18 @@ void Chunk::ClearNeighbors() { } void Chunk::Unlink() { - if (neighbor[Block::FACE_UP]) { - neighbor[Block::FACE_UP]->neighbor[Block::FACE_DOWN] = nullptr; - } - if (neighbor[Block::FACE_DOWN]) { - neighbor[Block::FACE_DOWN]->neighbor[Block::FACE_UP] = nullptr; - } - if (neighbor[Block::FACE_LEFT]) { - neighbor[Block::FACE_LEFT]->neighbor[Block::FACE_RIGHT] = nullptr; - } - if (neighbor[Block::FACE_RIGHT]) { - neighbor[Block::FACE_RIGHT]->neighbor[Block::FACE_LEFT] = nullptr; - } - if (neighbor[Block::FACE_FRONT]) { - neighbor[Block::FACE_FRONT]->neighbor[Block::FACE_BACK] = nullptr; - } - if (neighbor[Block::FACE_BACK]) { - neighbor[Block::FACE_BACK]->neighbor[Block::FACE_FRONT] = nullptr; + for (int face = 0; face < Block::FACE_COUNT; ++face) { + if (neighbor[face]) { + neighbor[face]->neighbor[Block::Opposite(Block::Face(face))] = nullptr; + } } } void Chunk::Relink() { - if (neighbor[Block::FACE_UP]) { - neighbor[Block::FACE_UP]->neighbor[Block::FACE_DOWN] = this; - } - if (neighbor[Block::FACE_DOWN]) { - neighbor[Block::FACE_DOWN]->neighbor[Block::FACE_UP] = this; - } - if (neighbor[Block::FACE_LEFT]) { - neighbor[Block::FACE_LEFT]->neighbor[Block::FACE_RIGHT] = this; - } - if (neighbor[Block::FACE_RIGHT]) { - neighbor[Block::FACE_RIGHT]->neighbor[Block::FACE_LEFT] = this; - } - if (neighbor[Block::FACE_FRONT]) { - neighbor[Block::FACE_FRONT]->neighbor[Block::FACE_BACK] = this; - } - if (neighbor[Block::FACE_BACK]) { - neighbor[Block::FACE_BACK]->neighbor[Block::FACE_FRONT] = this; + for (int face = 0; face < Block::FACE_COUNT; ++face) { + if (neighbor[face]) { + neighbor[face]->neighbor[Block::Opposite(Block::Face(face))] = this; + } } } @@ -371,24 +322,15 @@ int Chunk::GetLight(int index) const { return light[index]; } -float Chunk::GetVertexLight(int index, const BlockModel::Position &vtx, const BlockModel::Normal &norm) const { +float Chunk::GetVertexLight(int index, const BlockModel::Position &vtx, const Model::Normal &norm) const { float light = GetLight(index); Chunk::Pos pos(ToPos(index)); Block::Face direct_face(Block::NormalFace(norm)); - const Chunk *direct_chunk = this; - Chunk::Pos direct_pos(pos + Block::FaceNormal(direct_face)); - if (!InBounds(direct_pos)) { - if (HasNeighbor(direct_face)) { - direct_chunk = &GetNeighbor(direct_face); - direct_pos -= (Block::FaceNormal(direct_face) * Extent()); - float direct_light = direct_chunk->GetLight(direct_pos); - if (direct_light > light) { - light = direct_light; - } - } - } else { - float direct_light = direct_chunk->GetLight(direct_pos); + // tis okay + BlockLookup direct(const_cast(this), pos, Block::NormalFace(norm)); + if (direct) { + float direct_light = direct.GetLight(); if (direct_light > light) { light = direct_light; } @@ -413,8 +355,8 @@ bool Chunk::IsSurface(const Pos &pos) const { return false; } for (int face = 0; face < Block::FACE_COUNT; ++face) { - const Block *next = FindNext(pos, Block::Face(face)); - if (!next || !Type(*next).visible) { + BlockLookup next = BlockLookup(const_cast(this), pos, Block::Face(face)); + if (!next || !next.GetType().visible) { return true; } } @@ -422,12 +364,6 @@ bool Chunk::IsSurface(const Pos &pos) const { } -void Chunk::Allocate() { - blocks.resize(Size(), Block(0)); - light.resize(Size(), 0); -} - - void Chunk::Draw() { if (dirty) { Update(); @@ -509,14 +445,18 @@ void Chunk::Update() { for (size_t i = 0; i < Size(); ++i) { const BlockType &type = Type(blocks[i]); - if (!type.visible || Obstructed(i)) continue; + if (!type.visible || Obstructed(i).All()) continue; type.FillBlockModel(buf, ToTransform(i), vtx_counter); size_t vtx_begin = vtx_counter; vtx_counter += type.shape->VertexCount(); for (size_t vtx = vtx_begin; vtx < vtx_counter; ++vtx) { - buf.lights.emplace_back(GetVertexLight(i, buf.vertices[vtx], buf.normals[vtx])); + buf.lights.emplace_back(GetVertexLight( + i, + buf.vertices[vtx], + type.shape->VertexNormal(vtx - vtx_begin, blocks[i].Transform()) + )); } } @@ -524,94 +464,19 @@ void Chunk::Update() { dirty = false; } -bool Chunk::Obstructed(int idx) const { +Block::FaceSet Chunk::Obstructed(int idx) const { Chunk::Pos pos(ToPos(idx)); + Block::FaceSet result; - Chunk::Pos left_pos(pos + Chunk::Pos(-1, 0, 0)); - const Block *left_block = nullptr; - if (InBounds(left_pos)) { - left_block = &BlockAt(left_pos); - } else if (HasNeighbor(Block::FACE_LEFT)) { - left_pos += Chunk::Pos(Width(), 0, 0); - left_block = &GetNeighbor(Block::FACE_LEFT).BlockAt(left_pos); - } else { - return false; - } - if (!Type(*left_block).FaceFilled(*left_block, Block::FACE_RIGHT)) { - return false; - } - - Chunk::Pos right_pos(pos + Chunk::Pos(1, 0, 0)); - const Block *right_block = nullptr; - if (InBounds(right_pos)) { - right_block = &BlockAt(right_pos); - } else if (HasNeighbor(Block::FACE_RIGHT)) { - right_pos += Chunk::Pos(-Width(), 0, 0); - right_block = &GetNeighbor(Block::FACE_RIGHT).BlockAt(right_pos); - } else { - return false; - } - if (!Type(*right_block).FaceFilled(*right_block, Block::FACE_LEFT)) { - return false; - } - - Chunk::Pos down_pos(pos + Chunk::Pos(0, -1, 0)); - const Block *down_block = nullptr; - if (InBounds(down_pos)) { - down_block = &BlockAt(down_pos); - } else if (HasNeighbor(Block::FACE_DOWN)) { - down_pos += Chunk::Pos(0, Height(), 0); - down_block = &GetNeighbor(Block::FACE_DOWN).BlockAt(down_pos); - } else { - return false; - } - if (!Type(*down_block).FaceFilled(*down_block, Block::FACE_UP)) { - return false; - } - - Chunk::Pos up_pos(pos + Chunk::Pos(0, 1, 0)); - const Block *up_block = nullptr; - if (InBounds(up_pos)) { - up_block = &BlockAt(up_pos); - } else if (HasNeighbor(Block::FACE_UP)) { - up_pos += Chunk::Pos(0, -Height(), 0); - up_block = &GetNeighbor(Block::FACE_UP).BlockAt(up_pos); - } else { - return false; - } - if (!Type(*up_block).FaceFilled(*up_block, Block::FACE_DOWN)) { - return false; - } - - Chunk::Pos back_pos(pos + Chunk::Pos(0, 0, -1)); - const Block *back_block = nullptr; - if (InBounds(back_pos)) { - back_block = &BlockAt(back_pos); - } else if (HasNeighbor(Block::FACE_BACK)) { - back_pos += Chunk::Pos(0, 0, Depth()); - back_block = &GetNeighbor(Block::FACE_BACK).BlockAt(back_pos); - } else { - return false; - } - if (!Type(*back_block).FaceFilled(*back_block, Block::FACE_FRONT)) { - return false; - } - - Chunk::Pos front_pos(pos + Chunk::Pos(0, 0, 1)); - const Block *front_block = nullptr; - if (InBounds(front_pos)) { - front_block = &BlockAt(front_pos); - } else if (HasNeighbor(Block::FACE_FRONT)) { - front_pos += Chunk::Pos(0, 0, -Depth()); - front_block = &GetNeighbor(Block::FACE_FRONT).BlockAt(front_pos); - } else { - return false; - } - if (!Type(*front_block).FaceFilled(*front_block, Block::FACE_BACK)) { - return false; + for (int f = 0; f < Block::FACE_COUNT; ++f) { + Block::Face face = Block::Face(f); + BlockLookup next(const_cast(this), pos, face); + if (next && next.GetType().FaceFilled(next.GetBlock(), Block::Opposite(face))) { + result.Set(face); + } } - return true; + return result; } glm::mat4 Chunk::ToTransform(int idx) const { @@ -620,12 +485,13 @@ glm::mat4 Chunk::ToTransform(int idx) const { BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) -: chunk(c), pos(p), result(nullptr) { +: chunk(c), pos(p) { while (pos.x >= Chunk::Width()) { if (chunk->HasNeighbor(Block::FACE_RIGHT)) { chunk = &chunk->GetNeighbor(Block::FACE_RIGHT); pos.x -= Chunk::Width(); } else { + chunk = nullptr; return; } } @@ -634,6 +500,7 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) chunk = &chunk->GetNeighbor(Block::FACE_LEFT); pos.x += Chunk::Width(); } else { + chunk = nullptr; return; } } @@ -642,6 +509,7 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) chunk = &chunk->GetNeighbor(Block::FACE_UP); pos.y -= Chunk::Height(); } else { + chunk = nullptr; return; } } @@ -650,6 +518,7 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) chunk = &chunk->GetNeighbor(Block::FACE_DOWN); pos.y += Chunk::Height(); } else { + chunk = nullptr; return; } } @@ -658,6 +527,7 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) chunk = &chunk->GetNeighbor(Block::FACE_FRONT); pos.z -= Chunk::Depth(); } else { + chunk = nullptr; return; } } @@ -666,23 +536,18 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) chunk = &chunk->GetNeighbor(Block::FACE_BACK); pos.z += Chunk::Depth(); } else { + chunk = nullptr; return; } } - result = &chunk->BlockAt(pos); } BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p, Block::Face face) -: chunk(c), pos(p), result(nullptr) { +: chunk(c), pos(p) { pos += Block::FaceNormal(face); - if (Chunk::InBounds(pos)) { - result = &chunk->BlockAt(pos); - } else { + if (!Chunk::InBounds(pos)) { pos -= Block::FaceNormal(face) * Chunk::Extent(); - if (chunk->HasNeighbor(face)) { - chunk = &chunk->GetNeighbor(face); - result = &chunk->BlockAt(pos); - } + chunk = &chunk->GetNeighbor(face); } } @@ -787,7 +652,6 @@ Chunk &ChunkLoader::Generate(const Chunk::Pos &pos) { loaded.emplace_back(reg); Chunk &chunk = loaded.back(); chunk.Position(pos); - chunk.Allocate(); gen(chunk); Insert(chunk); return chunk; @@ -881,39 +745,31 @@ void ChunkLoader::GenerateSurrounding(const Chunk::Pos &pos) { } void ChunkLoader::Update() { - bool reused = false; - if (!to_generate.empty()) { - Chunk::Pos pos(to_generate.front()); - - 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); - reused = true; - break; - } - } + if (to_generate.empty()) { + return; + } - if (!reused) { - if (to_free.empty()) { - loaded.emplace_back(reg); - } else { - to_free.front().ClearNeighbors(); - loaded.splice(loaded.end(), to_free, to_free.begin()); - reused = true; - } - Chunk &chunk = loaded.back(); - chunk.Position(pos); - chunk.Allocate(); - gen(chunk); - Insert(chunk); + Chunk::Pos pos(to_generate.front()); + to_generate.pop_front(); + + 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); + return; } - to_generate.pop_front(); } - if (!reused && !to_free.empty()) { - to_free.pop_front(); + 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); + Insert(chunk); } }