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