| @ -0,0 +1,96 @@ | |||||
| #pragma once | |||||
| #include <vector> | |||||
| #include <array> | |||||
| template<typename T, size_t chunk_size = 16> | |||||
| struct cube { | |||||
| struct chunk_elem_t { | |||||
| size_t coord; | |||||
| T elem; | |||||
| }; | |||||
| struct chunk_t { | |||||
| std::array<std::array<std::vector<chunk_elem_t>, chunk_size>, chunk_size> data; | |||||
| }; | |||||
| struct row_t { | |||||
| size_t coord; | |||||
| std::shared_ptr<chunk_t> value; | |||||
| }; | |||||
| struct column_t { | |||||
| size_t coord; | |||||
| std::vector<row_t> value; | |||||
| }; | |||||
| std::vector<column_t> chunks; | |||||
| std::optional<T> at(size_t x, size_t y, size_t z) { | |||||
| auto column = std::ranges::find_if(chunks, [&](const column_t& col) { | |||||
| return col.coord == y/chunk_size; | |||||
| }); | |||||
| if(column == chunks.end()) return std::nullopt; | |||||
| auto row = std::ranges::find_if(column->value, [&](const row_t& row) { | |||||
| return row.coord == x/chunk_size; | |||||
| }); | |||||
| if(column->value.end() == row) return std::nullopt; | |||||
| auto& chunk_segment = row->value->data.at(x%chunk_size).at(y%chunk_size); | |||||
| auto position = std::ranges::find_if(chunk_segment, [&](const chunk_elem_t& item) { | |||||
| return item.coord == z; | |||||
| }); | |||||
| if(position == chunk_segment.end()) return std::nullopt; | |||||
| return position->elem; | |||||
| } | |||||
| void set(size_t x, size_t y, size_t z, T&& value) { | |||||
| auto column = std::ranges::find_if(chunks, [&](const column_t& col) { | |||||
| return col.coord == y/chunk_size; | |||||
| }); | |||||
| if(column == chunks.end()) { | |||||
| auto chunk = std::make_shared<chunk_t>(); | |||||
| chunks.push_back(column_t{ | |||||
| .coord = y / chunk_size, | |||||
| .value = { | |||||
| row_t{ | |||||
| .coord = x/chunk_size, | |||||
| .value = chunk | |||||
| } | |||||
| } | |||||
| }); | |||||
| chunk->data.at(x%chunk_size).at(y%chunk_size).push_back(chunk_elem_t{ | |||||
| .coord = z, | |||||
| .elem = std::move(value) | |||||
| }); | |||||
| return; | |||||
| } | |||||
| auto row = std::ranges::find_if(column->value, [&](const row_t& row) { | |||||
| return row.coord == x/chunk_size; | |||||
| }); | |||||
| if(column->value.end() == row) { | |||||
| auto chunk = std::make_shared<chunk_t>(); | |||||
| column->value.push_back( | |||||
| row_t{ | |||||
| .coord = x/chunk_size, | |||||
| .value = chunk | |||||
| } | |||||
| ); | |||||
| chunk->data.at(x%chunk_size).at(y%chunk_size).push_back(chunk_elem_t{ | |||||
| .coord = z, | |||||
| .elem = std::move(value) | |||||
| }); | |||||
| return; | |||||
| } | |||||
| auto& chunk_segment = row->value->data.at(x%chunk_size).at(y%chunk_size); | |||||
| auto position = std::ranges::find_if(chunk_segment, [&](const chunk_elem_t& item) { | |||||
| return item.coord == z; | |||||
| }); | |||||
| if(position == chunk_segment.end()) { | |||||
| chunk_segment.push_back(chunk_elem_t{ | |||||
| .coord = z, | |||||
| .elem = std::move(value) | |||||
| }); | |||||
| return; | |||||
| } | |||||
| position->elem = std::move(value); | |||||
| } | |||||
| }; | |||||