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