summary refs log tree commit diff
path: root/src/World/World.cpp
blob: 449ba2d9194b33c5835d563792898ff0af84f41a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "World.hpp"

namespace MC::World {

std::vector<World::ChunkData> World::get_visible_chunks(Vector<3> position) {
    auto visible_chunks = get_visible_chunk_indices(position);

    auto difference = visible_chunks;
    for (auto index : m_visible_chunks) {
        difference.erase(index);
    }

    if (!difference.empty()) {
        for (auto new_index: difference) {
            auto& data = get_or_generate(new_index);
            if (!data.mesh.has_value()) {
                auto mesh = data.chunk->mesh();
                data.mesh = GFX::Binder::load(mesh);
            }
        }
        m_visible_chunks = visible_chunks;
    }

    std::vector<World::ChunkData> chunks{};
    chunks.reserve(visible_chunks.size());
    for (auto index : visible_chunks) {
        chunks.push_back(get_or_generate(index));
    }

    return chunks;
}

std::unordered_set<ChunkIndex> World::get_visible_chunk_indices(Vector<3> position) const {
    int32_t center_x = std::round(position.x() / CHUNK_WIDTH);
    int32_t center_y = std::round(position.z() / CHUNK_HEIGHT);

    auto upper_x_bound = center_x + m_view_distance_radius;
    auto lower_x_bound = center_x - m_view_distance_radius;
    auto upper_y_bound = center_y + m_view_distance_radius;
    auto lower_y_bound = center_y - m_view_distance_radius;

    std::unordered_set<ChunkIndex> indices{};
    indices.reserve(m_view_distance_radius * m_view_distance_radius * 4);
    for (int32_t x = lower_x_bound; x < upper_x_bound; x++) {
        for (int32_t y = lower_y_bound; y < upper_y_bound; y++) {
            indices.emplace(x, y);
        }
    }

    return indices;
}

World::ChunkData& World::get_or_generate(ChunkIndex index) {
    auto entry = m_chunks.find(index);
    if (entry == m_chunks.end()) {
        auto chunk = m_generator.generate(index.x, index.y);
        ChunkData data{index, std::make_shared<Chunk>(chunk)};

        m_chunks.insert({index, data});
        return m_chunks.at(index);
    }

    return entry->second;
}


}