X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2Fchunk.cpp;h=7f2233e2def66a6e99dee791d6d2e0ce1a73b0ad;hb=3185bad87c06739e4ec19b456c7158437ba9621f;hp=f819ef9be8ecacdeb90219862dc399f554d78a58;hpb=4e3afb4c7631591b80cb7740a9b6f46da69b7ae4;p=blank.git diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index f819ef9..7f2233e 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -8,6 +8,7 @@ #include "Generator.hpp" #include "WorldCollision.hpp" #include "../app/Assets.hpp" +#include "../geometry/distance.hpp" #include "../graphics/BlockLighting.hpp" #include "../graphics/BlockMesh.hpp" #include "../graphics/Viewport.hpp" @@ -18,19 +19,20 @@ #include #include +#include +#include + namespace blank { -constexpr int Chunk::width; -constexpr int Chunk::height; -constexpr int Chunk::depth; +constexpr int Chunk::side; constexpr int Chunk::size; Chunk::Chunk(const BlockTypeRegistry &types) noexcept : types(&types) , neighbor{0} -, blocks{} +, gravity() , light{0} , generated(false) , lighted(false) @@ -43,6 +45,7 @@ Chunk::Chunk(const BlockTypeRegistry &types) noexcept Chunk::Chunk(Chunk &&other) noexcept : types(other.types) +, gravity(std::move(other.gravity)) , generated(other.generated) , lighted(other.lighted) , position(other.position) @@ -58,6 +61,7 @@ Chunk::Chunk(Chunk &&other) noexcept Chunk &Chunk::operator =(Chunk &&other) noexcept { types = other.types; std::copy(other.neighbor, other.neighbor + sizeof(neighbor), neighbor); + gravity = std::move(other.gravity); std::copy(other.blocks, other.blocks + sizeof(blocks), blocks); std::copy(other.light, other.light + sizeof(light), light); generated = other.generated; @@ -75,9 +79,9 @@ namespace { struct SetNode { Chunk *chunk; - Chunk::Pos pos; + RoughLocation::Fine pos; - SetNode(Chunk *chunk, Chunk::Pos pos) + SetNode(Chunk *chunk, RoughLocation::Fine pos) : chunk(chunk), pos(pos) { } int Get() const noexcept { return chunk->GetLight(pos); } @@ -85,6 +89,9 @@ struct SetNode { const BlockType &GetType() const noexcept { return chunk->Type(Chunk::ToIndex(pos)); } + int EmitLevel() const noexcept { return GetType().luminosity; } + bool EmitsLight() const noexcept { return EmitLevel() > 0; } + bool HasNext(Block::Face face) noexcept { const BlockType &type = GetType(); if (type.block_light && !type.luminosity) return false; @@ -103,10 +110,10 @@ struct UnsetNode int level; - UnsetNode(Chunk *chunk, Chunk::Pos pos) + UnsetNode(Chunk *chunk, RoughLocation::Fine pos) : SetNode(chunk, pos), level(Get()) { } - UnsetNode(const SetNode &set) + explicit UnsetNode(const SetNode &set) : SetNode(set), level(Get()) { } @@ -147,9 +154,13 @@ void work_dark() noexcept { for (int face = 0; face < Block::FACE_COUNT; ++face) { if (node.HasNext(Block::Face(face))) { UnsetNode other = node.GetNext(Block::Face(face)); - // TODO: if there a light source here with the same level this will err if (other.Get() != 0 && other.Get() < node.level) { - other.Set(0); + if (other.EmitsLight()) { + other.Set(other.EmitLevel()); + light_queue.emplace(other); + } else { + other.Set(0); + } dark_queue.emplace(other); } else { light_queue.emplace(other); @@ -168,6 +179,12 @@ void Chunk::SetBlock(int index, const Block &block) noexcept { blocks[index] = block; Invalidate(); + if (old_type.gravity && !new_type.gravity) { + gravity.erase(index); + } else if (new_type.gravity && !old_type.gravity) { + gravity.insert(index); + } + if (!lighted || &old_type == &new_type) return; if (new_type.luminosity > old_type.luminosity) { @@ -194,7 +211,7 @@ void Chunk::SetBlock(int index, const Block &block) noexcept { } else if (!new_type.block_light && old_type.block_light) { // obstacle removed int level = 0; - Pos pos(ToPos(index)); + RoughLocation::Fine pos(ToPos(index)); for (int face = 0; face < Block::FACE_COUNT; ++face) { BlockLookup next_block(this, pos, Block::Face(face)); if (next_block) { @@ -211,10 +228,10 @@ void Chunk::SetBlock(int index, const Block &block) noexcept { void Chunk::ScanLights() { int idx = 0; - Pos pos(0, 0, 0); - for (; pos.z < depth; ++pos.z) { - for (pos.y = 0; pos.y < height; ++pos.y) { - for (pos.x = 0; pos.x < width; ++pos.x, ++idx) { + RoughLocation::Fine pos(0, 0, 0); + for (; pos.z < side; ++pos.z) { + for (pos.y = 0; pos.y < side; ++pos.y) { + for (pos.x = 0; pos.x < side; ++pos.x, ++idx) { const BlockType &type = Type(blocks[idx]); if (type.luminosity) { SetLight(idx, type.luminosity); @@ -227,6 +244,15 @@ void Chunk::ScanLights() { lighted = true; } +void Chunk::ScanActive() { + gravity.clear(); + for (int index = 0; index < size; ++index) { + if (Type(index).gravity) { + gravity.insert(gravity.end(), index); + } + } +} + void Chunk::SetNeighbor(Block::Face face, Chunk &other) noexcept { neighbor[face] = &other; other.neighbor[Block::Opposite(face)] = this; @@ -253,7 +279,7 @@ int Chunk::GetLight(int index) const noexcept { return light[index]; } -float Chunk::GetVertexLight(const Pos &pos, const BlockMesh::Position &vtx, const EntityMesh::Normal &norm) const noexcept { +float Chunk::GetVertexLight(const RoughLocation::Fine &pos, const BlockMesh::Position &vtx, const EntityMesh::Normal &norm) const noexcept { int index = ToIndex(pos); float light = GetLight(index); @@ -343,7 +369,21 @@ float Chunk::GetVertexLight(const Pos &pos, const BlockMesh::Position &vtx, cons } -bool Chunk::IsSurface(const Pos &pos) const noexcept { +glm::vec3 Chunk::GravityAt(const ExactLocation &coords) const noexcept { + glm::vec3 grav(0.0f); + for (int index : gravity) { + RoughLocation::Fine block_pos(ToPos(index)); + ExactLocation block_coords(position, ToCoords(block_pos)); + // trust that block type hasn't changed + grav += Type(index).gravity->GetGravity( + coords.Difference(block_coords).Absolute(), + ToTransform(block_pos, index)); + } + return grav; +} + + +bool Chunk::IsSurface(const RoughLocation::Fine &pos) const noexcept { const Block &block = BlockAt(pos); if (!Type(block).visible) { return false; @@ -360,23 +400,31 @@ bool Chunk::IsSurface(const Pos &pos) const noexcept { bool Chunk::Intersection( const Ray &ray, - const glm::mat4 &M, + const ExactLocation::Coarse &reference, WorldCollision &coll ) noexcept { int idx = 0; coll.chunk = this; coll.block = -1; coll.depth = std::numeric_limits::infinity(); - for (int z = 0; z < depth; ++z) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x, ++idx) { + for (int z = 0; z < side; ++z) { + for (int y = 0; y < side; ++y) { + for (int x = 0; x < side; ++x, ++idx) { const BlockType &type = Type(idx); if (!type.collision || !type.shape) { continue; } + RoughLocation::Fine pos(x, y, z); + + // center of the blok relative to the ray + glm::vec3 relative_center(glm::vec3((position - reference) * ExactLocation::Extent() + pos) + 0.5f); + if (ray.DistanceSquared(relative_center) > 3.0f) { + continue; + } + float cur_dist; glm::vec3 cur_norm; - if (type.shape->Intersects(ray, M * ToTransform(Pos(x, y, z), idx), cur_dist, cur_norm)) { + if (type.shape->Intersects(ray, ToTransform(reference, pos, idx), cur_dist, cur_norm)) { if (cur_dist < coll.depth) { coll.block = idx; coll.depth = cur_dist; @@ -408,14 +456,82 @@ bool Chunk::Intersection( if (!blank::Intersection(box, Mbox, Bounds(), Mchunk, penetration, normal)) { return false; } - for (int idx = 0, z = 0; z < depth; ++z) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x, ++idx) { + + // box's origin relative to the chunk + const glm::vec3 box_coords(Mbox[3] - Mchunk[3]); + const float box_rad = box.OriginRadius(); + + // assume a bounding radius of 2 for blocks + constexpr float block_rad = 2.0f; + const float bb_radius = box_rad + block_rad; + + const RoughLocation::Fine begin(glm::max( + RoughLocation::Fine(0), + RoughLocation::Fine(glm::floor(box_coords - bb_radius)) + )); + const RoughLocation::Fine end(glm::min( + RoughLocation::Fine(side - 1), + RoughLocation::Fine(glm::ceil(box_coords + bb_radius)) + ) - 1); + + for (RoughLocation::Fine pos(begin); pos.z < end.y; ++pos.z) { + for (pos.y = begin.y; pos.y < end.y; ++pos.y) { + for (pos.x = begin.x; pos.x < end.x; ++pos.x) { + int idx = ToIndex(pos); + const BlockType &type = Type(idx); + if (!type.collision || !type.shape) { + continue; + } + if (type.shape->Intersects(Mchunk * ToTransform(pos, idx), box, Mbox, penetration, normal)) { + col.emplace_back(this, idx, penetration, normal); + any = true; + } + } + } + } + return any; +} + +bool Chunk::Intersection( + const Entity &entity, + const glm::mat4 &Mentity, + const glm::mat4 &Mchunk, + std::vector &col +) noexcept { + // entity's origin relative to the chunk + const glm::vec3 entity_coords(Mentity[3] - Mchunk[3]); + const float ec_radius = entity.Radius() + Radius(); + + if (glm::distance2(entity_coords, Center()) > ec_radius * ec_radius) { + return false; + } + + bool any = false; + float penetration; + glm::vec3 normal; + + // assume a bounding radius of 2 for blocks + constexpr float block_rad = 2.0f; + const float eb_radius = entity.Radius() + block_rad; + + const RoughLocation::Fine begin(glm::max( + RoughLocation::Fine(0), + RoughLocation::Fine(glm::floor(entity_coords - eb_radius)) + )); + const RoughLocation::Fine end(glm::min( + RoughLocation::Fine(side), + RoughLocation::Fine(glm::ceil(entity_coords + eb_radius)) + )); + + for (RoughLocation::Fine pos(begin); pos.z < end.z; ++pos.z) { + for (pos.y = begin.y; pos.y < end.y; ++pos.y) { + for (pos.x = begin.x; pos.x < end.x; ++pos.x) { + int idx = ToIndex(pos); const BlockType &type = Type(idx); if (!type.collision || !type.shape) { continue; } - if (type.shape->Intersects(Mchunk * ToTransform(Pos(x, y, z), idx), box, Mbox, penetration, normal)) { + if (type.shape->Intersects(Mchunk * ToTransform(pos, idx), entity.Bounds(), Mentity, penetration, normal)) { col.emplace_back(this, idx, penetration, normal); any = true; } @@ -447,11 +563,11 @@ void Chunk::Update(BlockMesh &model) noexcept { if (idx_count > 0) { int idx = 0; BlockMesh::Index vtx_counter = 0; - for (size_t z = 0; z < depth; ++z) { - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; ++x, ++idx) { + for (size_t z = 0; z < side; ++z) { + for (size_t y = 0; y < side; ++y) { + for (size_t x = 0; x < side; ++x, ++idx) { const BlockType &type = Type(BlockAt(idx)); - const Pos pos(x, y, z); + const RoughLocation::Fine pos(x, y, z); if (!type.visible || !type.shape || Obstructed(pos).All()) continue; @@ -475,7 +591,7 @@ void Chunk::Update(BlockMesh &model) noexcept { ClearMesh(); } -Block::FaceSet Chunk::Obstructed(const Pos &pos) const noexcept { +Block::FaceSet Chunk::Obstructed(const RoughLocation::Fine &pos) const noexcept { Block::FaceSet result; for (int f = 0; f < Block::FACE_COUNT; ++f) { @@ -489,17 +605,21 @@ Block::FaceSet Chunk::Obstructed(const Pos &pos) const noexcept { return result; } -glm::mat4 Chunk::ToTransform(const Pos &pos, int idx) const noexcept { +glm::mat4 Chunk::ToTransform(const RoughLocation::Fine &pos, int idx) const noexcept { return glm::translate(ToCoords(pos)) * BlockAt(idx).Transform(); } +glm::mat4 Chunk::ToTransform(const ExactLocation::Coarse &ref, const RoughLocation::Fine &pos, int idx) const noexcept { + return glm::translate(ExactLocation::Fine((position - ref) * ExactLocation::Extent()) + ToCoords(pos)) * BlockAt(idx).Transform(); +} + -BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept +BlockLookup::BlockLookup(Chunk *c, const RoughLocation::Fine &p) noexcept : chunk(c), pos(p) { - while (pos.x >= Chunk::width) { + while (pos.x >= Chunk::side) { if (chunk->HasNeighbor(Block::FACE_RIGHT)) { chunk = &chunk->GetNeighbor(Block::FACE_RIGHT); - pos.x -= Chunk::width; + pos.x -= Chunk::side; } else { chunk = nullptr; return; @@ -508,16 +628,16 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept while (pos.x < 0) { if (chunk->HasNeighbor(Block::FACE_LEFT)) { chunk = &chunk->GetNeighbor(Block::FACE_LEFT); - pos.x += Chunk::width; + pos.x += Chunk::side; } else { chunk = nullptr; return; } } - while (pos.y >= Chunk::height) { + while (pos.y >= Chunk::side) { if (chunk->HasNeighbor(Block::FACE_UP)) { chunk = &chunk->GetNeighbor(Block::FACE_UP); - pos.y -= Chunk::height; + pos.y -= Chunk::side; } else { chunk = nullptr; return; @@ -526,16 +646,16 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept while (pos.y < 0) { if (chunk->HasNeighbor(Block::FACE_DOWN)) { chunk = &chunk->GetNeighbor(Block::FACE_DOWN); - pos.y += Chunk::height; + pos.y += Chunk::side; } else { chunk = nullptr; return; } } - while (pos.z >= Chunk::depth) { + while (pos.z >= Chunk::side) { if (chunk->HasNeighbor(Block::FACE_FRONT)) { chunk = &chunk->GetNeighbor(Block::FACE_FRONT); - pos.z -= Chunk::depth; + pos.z -= Chunk::side; } else { chunk = nullptr; return; @@ -544,7 +664,7 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept while (pos.z < 0) { if (chunk->HasNeighbor(Block::FACE_BACK)) { chunk = &chunk->GetNeighbor(Block::FACE_BACK); - pos.z += Chunk::depth; + pos.z += Chunk::side; } else { chunk = nullptr; return; @@ -552,11 +672,11 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept } } -BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p, Block::Face face) noexcept +BlockLookup::BlockLookup(Chunk *c, const RoughLocation::Fine &p, Block::Face face) noexcept : chunk(c), pos(p) { pos += Block::FaceNormal(face); if (!Chunk::InBounds(pos)) { - pos -= Block::FaceNormal(face) * Chunk::Extent(); + pos -= Block::FaceNormal(face) * ExactLocation::Extent(); chunk = &chunk->GetNeighbor(face); } } @@ -609,7 +729,7 @@ int ChunkLoader::ToLoad() const noexcept { bool ChunkLoader::LoadOne() { if (!store.HasMissing()) return false; - Chunk::Pos pos = store.NextMissing(); + ExactLocation::Coarse pos = store.NextMissing(); Chunk *chunk = store.Allocate(pos); if (!chunk) { // chunk store corrupted? @@ -629,9 +749,9 @@ bool ChunkLoader::LoadOne() { return generated; } - Chunk::Pos begin(pos - Chunk::Pos(1)); - Chunk::Pos end(pos + Chunk::Pos(2)); - for (Chunk::Pos iter(begin); iter.z < end.z; ++iter.z) { + ExactLocation::Coarse begin(pos - ExactLocation::Coarse(1)); + ExactLocation::Coarse end(pos + ExactLocation::Coarse(2)); + for (ExactLocation::Coarse iter(begin); iter.z < end.z; ++iter.z) { for (iter.y = begin.y; iter.y < end.y; ++iter.y) { for (iter.x = begin.x; iter.x < end.x; ++iter.x) { if (index->IsBorder(iter)) continue; @@ -675,7 +795,7 @@ int ChunkRenderer::MissingChunks() const noexcept { return index.MissingChunks(); } -void ChunkRenderer::LoadTextures(const AssetLoader &loader, const TextureIndex &tex_index) { +void ChunkRenderer::LoadTextures(const AssetLoader &loader, const ResourceIndex &tex_index) { block_tex.Bind(); loader.LoadTextures(tex_index, block_tex); block_tex.FilterNearest(); @@ -699,22 +819,28 @@ void ChunkRenderer::Render(Viewport &viewport) { chunk_prog.SetTexture(block_tex); chunk_prog.SetFogDensity(fog_density); + Frustum frustum(glm::transpose(chunk_prog.GetVP())); + AABB box; + for (int i = 0; i < index.TotalChunks(); ++i) { if (!index[i]) continue; - glm::mat4 m(index[i]->Transform(index.Base())); - glm::mat4 mvp(chunk_prog.GetVP() * m); - if (!CullTest(Chunk::Bounds(), mvp)) { + box.min = (index[i]->Position() - index.Base()) * ExactLocation::Extent(); + box.max = box.min + ExactLocation::FExtent(); + + if (!CullTest(box, frustum)) { if (index[i]->ShouldUpdateMesh()) { index[i]->Update(models[i]); } - chunk_prog.SetM(m); - models[i].Draw(); + if (!models[i].Empty()) { + chunk_prog.SetM(index[i]->Transform(index.Base())); + models[i].Draw(); + } } } } -ChunkIndex::ChunkIndex(ChunkStore &store, const Chunk::Pos &base, int extent) +ChunkIndex::ChunkIndex(ChunkStore &store, const ExactLocation::Coarse &base, int extent) : store(store) , base(base) , extent(extent) @@ -731,22 +857,22 @@ ChunkIndex::~ChunkIndex() { Clear(); } -bool ChunkIndex::InRange(const Chunk::Pos &pos) const noexcept { +bool ChunkIndex::InRange(const ExactLocation::Coarse &pos) const noexcept { return Distance(pos) <= extent; } -bool ChunkIndex::IsBorder(const Chunk::Pos &pos) const noexcept { +bool ChunkIndex::IsBorder(const ExactLocation::Coarse &pos) const noexcept { return Distance(pos) == extent; } -int ChunkIndex::Distance(const Chunk::Pos &pos) const noexcept { +int ChunkIndex::Distance(const ExactLocation::Coarse &pos) const noexcept { return manhattan_radius(pos - base); } -bool ChunkIndex::HasAllSurrounding(const Chunk::Pos &pos) const noexcept { - Chunk::Pos begin(pos - Chunk::Pos(1)); - Chunk::Pos end(pos + Chunk::Pos(2)); - for (Chunk::Pos iter(begin); iter.z < end.z; ++iter.z) { +bool ChunkIndex::HasAllSurrounding(const ExactLocation::Coarse &pos) const noexcept { + ExactLocation::Coarse begin(pos - ExactLocation::Coarse(1)); + ExactLocation::Coarse end(pos + ExactLocation::Coarse(2)); + for (ExactLocation::Coarse iter(begin); iter.z < end.z; ++iter.z) { for (iter.y = begin.y; iter.y < end.y; ++iter.y) { for (iter.x = begin.x; iter.x < end.x; ++iter.x) { if (!Get(iter)) return false; @@ -756,8 +882,8 @@ bool ChunkIndex::HasAllSurrounding(const Chunk::Pos &pos) const noexcept { return true; } -int ChunkIndex::IndexOf(const Chunk::Pos &pos) const noexcept { - Chunk::Pos mod_pos( +int ChunkIndex::IndexOf(const ExactLocation::Coarse &pos) const noexcept { + ExactLocation::Coarse mod_pos( GetCol(pos.x), GetCol(pos.y), GetCol(pos.z) @@ -767,18 +893,18 @@ int ChunkIndex::IndexOf(const Chunk::Pos &pos) const noexcept { + mod_pos.z * stride.z; } -Chunk::Pos ChunkIndex::PositionOf(int i) const noexcept { - Chunk::Pos zero_pos( +ExactLocation::Coarse ChunkIndex::PositionOf(int i) const noexcept { + ExactLocation::Coarse zero_pos( (i / stride.x) % side_length, (i / stride.y) % side_length, (i / stride.z) % side_length ); - Chunk::Pos zero_base( + ExactLocation::Coarse zero_base( GetCol(base.x), GetCol(base.y), GetCol(base.z) ); - Chunk::Pos base_relative(zero_pos - zero_base); + ExactLocation::Coarse base_relative(zero_pos - zero_base); if (base_relative.x > extent) base_relative.x -= side_length; else if (base_relative.x < -extent) base_relative.x += side_length; if (base_relative.y > extent) base_relative.y -= side_length; @@ -788,7 +914,7 @@ Chunk::Pos ChunkIndex::PositionOf(int i) const noexcept { return base + base_relative; } -Chunk *ChunkIndex::Get(const Chunk::Pos &pos) noexcept { +Chunk *ChunkIndex::Get(const ExactLocation::Coarse &pos) noexcept { if (InRange(pos)) { return chunks[IndexOf(pos)]; } else { @@ -796,7 +922,7 @@ Chunk *ChunkIndex::Get(const Chunk::Pos &pos) noexcept { } } -const Chunk *ChunkIndex::Get(const Chunk::Pos &pos) const noexcept { +const Chunk *ChunkIndex::Get(const ExactLocation::Coarse &pos) const noexcept { if (InRange(pos)) { return chunks[IndexOf(pos)]; } else { @@ -804,10 +930,10 @@ const Chunk *ChunkIndex::Get(const Chunk::Pos &pos) const noexcept { } } -void ChunkIndex::Rebase(const Chunk::Pos &new_base) { +void ChunkIndex::Rebase(const ExactLocation::Coarse &new_base) { if (new_base == base) return; - Chunk::Pos diff(new_base - base); + ExactLocation::Coarse diff(new_base - base); if (manhattan_radius(diff) > extent) { // that's more than half, so probably not worth shifting @@ -906,7 +1032,7 @@ void ChunkIndex::Unset(int index) noexcept { } } -Chunk::Pos ChunkIndex::NextMissing() noexcept { +ExactLocation::Coarse ChunkIndex::NextMissing() noexcept { if (MissingChunks() > 0) { int roundtrip = last_missing; last_missing = (last_missing + 1) % total_length; @@ -933,7 +1059,7 @@ ChunkStore::~ChunkStore() { } -ChunkIndex &ChunkStore::MakeIndex(const Chunk::Pos &pos, int extent) { +ChunkIndex &ChunkStore::MakeIndex(const ExactLocation::Coarse &pos, int extent) { indices.emplace_back(*this, pos, extent); return indices.back(); } @@ -949,7 +1075,7 @@ void ChunkStore::UnregisterIndex(ChunkIndex &index) { } } -ChunkIndex *ChunkStore::ClosestIndex(const Chunk::Pos &pos) { +ChunkIndex *ChunkStore::ClosestIndex(const ExactLocation::Coarse &pos) { ChunkIndex *closest_index = nullptr; int closest_distance = std::numeric_limits::max(); @@ -964,7 +1090,7 @@ ChunkIndex *ChunkStore::ClosestIndex(const Chunk::Pos &pos) { return closest_index; } -Chunk *ChunkStore::Get(const Chunk::Pos &pos) { +Chunk *ChunkStore::Get(const ExactLocation::Coarse &pos) noexcept { for (ChunkIndex &index : indices) { Chunk *chunk = index.Get(pos); if (chunk) { @@ -974,7 +1100,17 @@ Chunk *ChunkStore::Get(const Chunk::Pos &pos) { return nullptr; } -Chunk *ChunkStore::Allocate(const Chunk::Pos &pos) { +const Chunk *ChunkStore::Get(const ExactLocation::Coarse &pos) const noexcept { + for (const ChunkIndex &index : indices) { + const Chunk *chunk = index.Get(pos); + if (chunk) { + return chunk; + } + } + return nullptr; +} + +Chunk *ChunkStore::Allocate(const ExactLocation::Coarse &pos) { Chunk *chunk = Get(pos); if (chunk) { return chunk; @@ -994,7 +1130,7 @@ Chunk *ChunkStore::Allocate(const Chunk::Pos &pos) { } for (int i = 0; i < Block::FACE_COUNT; ++i) { Block::Face face = Block::Face(i); - Chunk::Pos neighbor_pos(pos + Block::FaceNormal(face)); + ExactLocation::Coarse neighbor_pos(pos + Block::FaceNormal(face)); Chunk *neighbor = Get(neighbor_pos); if (neighbor) { chunk->SetNeighbor(face, *neighbor); @@ -1020,13 +1156,13 @@ int ChunkStore::EstimateMissing() const noexcept { return missing; } -Chunk::Pos ChunkStore::NextMissing() noexcept { +ExactLocation::Coarse ChunkStore::NextMissing() noexcept { for (ChunkIndex &index : indices) { if (index.MissingChunks()) { return index.NextMissing(); } } - return Chunk::Pos(0, 0, 0); + return ExactLocation::Coarse(0, 0, 0); } void ChunkStore::Clean() {