| @ -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); | |||
| } | |||
| }; | |||