Generational id
This commit is contained in:
parent
8d0c9194b0
commit
ff9942691a
2
TODO.md
2
TODO.md
|
@ -37,6 +37,8 @@
|
|||
- [ ] ZeroMQ
|
||||
- [x] Logger
|
||||
- [ ] FastNoiseSIMD / HastyNoise double precision
|
||||
- [ ] Generation identifier
|
||||
- [ ] Limit map usage
|
||||
|
||||
## Rendering
|
||||
- [x] Render triangle
|
||||
|
|
|
@ -110,15 +110,16 @@ namespace contouring {
|
|||
|
||||
void FlatDualMC::render(const surrounding::corners &surrounding, buffer::ShortIndexed::Data &out) const {
|
||||
const int SIZE = CHUNK_LENGTH + 3;
|
||||
std::vector<dualmc::DualMC<float>::Point> grid;
|
||||
std::array<dualmc::DualMC<float>::Point, SIZE * SIZE * SIZE> grid;
|
||||
{
|
||||
grid.reserve(SIZE * SIZE * SIZE);
|
||||
for (int z = 0; z < SIZE; z++) {
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
auto &cell = grid[((z * SIZE) + y) * SIZE + x];
|
||||
const auto &chunk = surrounding[(z >= CHUNK_LENGTH) + (y >= CHUNK_LENGTH)*2 + (x >= CHUNK_LENGTH)*4];
|
||||
const auto &voxel = chunk->get(glm::toIdx(x % CHUNK_LENGTH, y % CHUNK_LENGTH, z % CHUNK_LENGTH));
|
||||
grid.emplace_back(voxel.density() * 1.f / world::Voxel::DENSITY_MAX, voxel.material());
|
||||
cell.x = voxel.density() * 1.f / world::Voxel::DENSITY_MAX;
|
||||
cell.w = voxel.material();
|
||||
}}}
|
||||
}
|
||||
{
|
||||
|
|
|
@ -36,9 +36,9 @@ namespace contouring {
|
|||
safe_queue<std::pair<area_<chunk_pos>, buffer::ShortIndexed::Data>> loadedQueue;
|
||||
|
||||
struct report {
|
||||
circular_buffer<float> count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
circular_buffer<float> load = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> loaded = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
report_buffer count;
|
||||
report_buffer load;
|
||||
report_buffer loaded;
|
||||
} reports;
|
||||
|
||||
bool running = true;
|
||||
|
|
|
@ -34,9 +34,9 @@ namespace contouring {
|
|||
safe_queue<std::pair<area_<chunk_pos>, buffer::ShortIndexed::Data>> loadedQueue;
|
||||
|
||||
struct report {
|
||||
circular_buffer<float> count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
circular_buffer<float> load = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> loaded = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
report_buffer count;
|
||||
report_buffer load;
|
||||
report_buffer loaded;
|
||||
} reports;
|
||||
|
||||
bool running = true;
|
||||
|
|
|
@ -25,4 +25,8 @@ namespace data {
|
|||
return buffer[last];
|
||||
}
|
||||
};
|
||||
|
||||
struct report_buffer: circular_buffer<float> {
|
||||
report_buffer() : circular_buffer(256, 0) {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
namespace data::generational {
|
||||
struct id {
|
||||
id(size_t index, size_t generation = 0): index(index), generation(generation) { }
|
||||
id(): id(0) { }
|
||||
size_t index;
|
||||
size_t generation;
|
||||
|
||||
bool operator==(const id &i) const { return index == i.index && generation == i.generation; }
|
||||
};
|
||||
|
||||
class allocator {
|
||||
public:
|
||||
allocator() { }
|
||||
template <typename C>
|
||||
allocator(const C& map) {
|
||||
for(const auto& [key, _]: map) {
|
||||
if (const auto size = entries.size(); key >= size) {
|
||||
entries.resize(key + 1);
|
||||
for (size_t i = size; i < entries.size(); i++) {
|
||||
entries[i].is_live = false;
|
||||
freed.push_back(i);
|
||||
}
|
||||
}
|
||||
assert(!entries[key].is_live);
|
||||
entries[key].is_live = true;
|
||||
}
|
||||
}
|
||||
id alloc() {
|
||||
if(freed.empty()) {
|
||||
const auto idx = entries.size();
|
||||
entries.emplace_back();
|
||||
return id(idx);
|
||||
} else {
|
||||
const auto idx = freed.back();
|
||||
freed.pop_back();
|
||||
auto &entry = entries[idx];
|
||||
assert(!entry.is_live);
|
||||
entry.is_live = true;
|
||||
return id(idx, ++entries[idx].generation);
|
||||
}
|
||||
}
|
||||
bool is_live(id id) const {
|
||||
return id.index < entries.size() &&
|
||||
entries[id.index].is_live &&
|
||||
entries[id.index].generation == id.generation;
|
||||
}
|
||||
bool free(id id) {
|
||||
if(!is_live(id))
|
||||
return false;
|
||||
|
||||
entries[id.index].is_live = false;
|
||||
freed.push_back(id.index);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
struct entry {
|
||||
bool is_live = true;
|
||||
size_t generation = 0;
|
||||
};
|
||||
std::vector<entry> entries;
|
||||
std::vector<size_t> freed;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class vector {
|
||||
public:
|
||||
vector() { }
|
||||
template<typename C>
|
||||
vector(const C& map) {
|
||||
for(const auto& [key, value]: map) {
|
||||
if (const auto size = entries.size(); key >= size) {
|
||||
entries.resize(key + 1);
|
||||
}
|
||||
entries[key].value = value;
|
||||
}
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
if(!entries[i].value.has_value())
|
||||
freed.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
id push(const T& in) {
|
||||
if(freed.empty()) {
|
||||
const auto idx = entries.size();
|
||||
entries.emplace_back(in);
|
||||
return id(idx);
|
||||
} else {
|
||||
const auto idx = freed.back();
|
||||
freed.pop_back();
|
||||
auto &entry = entries[idx];
|
||||
assert(!entry.value.has_value());
|
||||
entry.value = in;
|
||||
return id(idx, ++entries[idx].generation);
|
||||
}
|
||||
}
|
||||
template <typename... _Args>
|
||||
id emplace(_Args &&... __args) {
|
||||
if(freed.empty()) {
|
||||
const auto idx = entries.size();
|
||||
entries.emplace_back(std::forward<_Args>(__args)...);
|
||||
return id(idx);
|
||||
} else {
|
||||
const auto idx = freed.back();
|
||||
freed.pop_back();
|
||||
auto &entry = entries[idx];
|
||||
assert(!entry.value.has_value());
|
||||
entry.value = std::make_optional<T>(std::forward<_Args>(__args)...);
|
||||
return id(idx, ++entries[idx].generation);
|
||||
}
|
||||
}
|
||||
bool put(id idx, const T& in) {
|
||||
if(idx.index >= entries.size())
|
||||
return false;
|
||||
|
||||
if(entries[idx.index].generation != idx.generation || entries[idx.index].value.has_value())
|
||||
return false;
|
||||
|
||||
entries[idx.index].value = in;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool contains(id idx) const {
|
||||
return idx.index < entries.size() &&
|
||||
entries[idx.index].generation == idx.generation &&
|
||||
entries[idx.index].value.has_value();
|
||||
}
|
||||
|
||||
bool free(id idx) {
|
||||
if(!contains(idx))
|
||||
return false;
|
||||
|
||||
entries[idx.index].value = std::nullopt;
|
||||
freed.push_back(idx.index);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename apply>
|
||||
void iter(apply fn) const {
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
const auto &entry = entries[i];
|
||||
if(entry.value.has_value()) {
|
||||
fn(id(i, entry.generation), entry.value.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename extractor>
|
||||
void extract(extractor fn) {
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
auto &entry = entries[i];
|
||||
if(entry.value.has_value()) {
|
||||
if(fn(id(i, entry.generation), entry.value.value()))
|
||||
entry.value = std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return std::count_if(entries.begin(), entries.end(),
|
||||
[](const entry &e) { return e.value.has_value(); });
|
||||
}
|
||||
|
||||
private:
|
||||
struct entry {
|
||||
entry(): value(std::nullopt), generation(0) { }
|
||||
entry(const T &in, size_t gen = 0):
|
||||
value(in), generation(gen) { }
|
||||
std::optional<T> value;
|
||||
size_t generation;
|
||||
};
|
||||
std::vector<entry> entries;
|
||||
std::vector<size_t> freed;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<data::generational::id> {
|
||||
std::size_t operator()(const data::generational::id& i) const noexcept {
|
||||
return std::hash<size_t>{}(i.index);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -167,7 +167,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::Begin("Editor", &options.editor_show, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if (state.look_at.has_value()) {
|
||||
const auto &look = state.look_at.value();
|
||||
ImGui::Text("Look at: (%ld: %lld, %lld, %lld) (%s, %.1f)", look.pos.first, look.pos.second.x, look.pos.second.y, look.pos.second.z,
|
||||
ImGui::Text("Look at: (%ld: %lld, %lld, %lld) (%s, %.1f)", look.pos.first.index, look.pos.second.x, look.pos.second.y, look.pos.second.z,
|
||||
world::materials::textures[look.value.material()].c_str(), look.value.density() * 1. / world::Voxel::DENSITY_MAX);
|
||||
const auto w_pos = look.pos.second + look.offset;
|
||||
ImGui::Text("(%.3f, %.3f, %.3f)", w_pos.x * 1. / options.voxel_density, w_pos.y * 1. / options.voxel_density, w_pos.z * 1. / options.voxel_density);
|
||||
|
|
27
src/state.h
27
src/state.h
|
@ -17,14 +17,15 @@
|
|||
#include "contouring/index.hpp"
|
||||
|
||||
inline glm::vec4 fromHex(const std::string& str) {
|
||||
int rgb[3] = {UCHAR_MAX};
|
||||
std::array<int, 3> rgb = {UCHAR_MAX};
|
||||
sscanf(str.c_str() + 1, "%02X%02X%02X", (unsigned int *)&rgb[0], (unsigned int *)&rgb[1], (unsigned int *)&rgb[2]);
|
||||
return glm::vec4(rgb[0] * 1.f / UCHAR_MAX, rgb[1] * 1.f / UCHAR_MAX, rgb[2] * 1.f / UCHAR_MAX, 1);
|
||||
}
|
||||
inline std::string toHexa(const glm::vec4& rgb) {
|
||||
auto out = (char*)malloc(8 * sizeof(char));
|
||||
sprintf(out, "#%02X%02X%02X", (int)(rgb.x * UCHAR_MAX), (int)(rgb.y * UCHAR_MAX), (int)(rgb.z * UCHAR_MAX));
|
||||
return std::string(out);
|
||||
std::ostringstream sstr;
|
||||
sstr << std::hex << std::setw(2) << std::setfill('0') <<
|
||||
static_cast<int>(rgb.x * UCHAR_MAX) << static_cast<int>(rgb.y * UCHAR_MAX) << static_cast<int>(rgb.z * UCHAR_MAX) << std::endl;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
/// Savable game options
|
||||
|
@ -107,9 +108,9 @@ struct options {
|
|||
{"mode", contouring::names[contouring_idx]},
|
||||
{"options", toml::table()}
|
||||
}));
|
||||
for(const auto opt: contouring_data) {
|
||||
if(!opt.second.empty())
|
||||
config["mesh"]["options"].as_table()->insert_or_assign(opt.first, opt.second);
|
||||
for(const auto& [key, val]: contouring_data) {
|
||||
if(!val.empty())
|
||||
config["mesh"]["options"].as_table()->insert_or_assign(key, val);
|
||||
}
|
||||
|
||||
config.insert_or_assign("camera", toml::table({
|
||||
|
@ -185,7 +186,7 @@ struct state {
|
|||
|
||||
std::shared_ptr<contouring::Abstract> contouring;
|
||||
|
||||
char console_buffer[256];
|
||||
std::array<char, 256> console_buffer;
|
||||
};
|
||||
|
||||
/// Readonly metrics
|
||||
|
@ -193,11 +194,11 @@ struct reports {
|
|||
struct main {
|
||||
size_t tris_count = 0;
|
||||
size_t models_count = 0;
|
||||
circular_buffer<float> fps = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> update = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> render = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> swap = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> wait = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
report_buffer fps;
|
||||
report_buffer update;
|
||||
report_buffer render;
|
||||
report_buffer swap;
|
||||
report_buffer wait;
|
||||
} main;
|
||||
world::Universe::report world;
|
||||
};
|
|
@ -26,26 +26,29 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
|
|||
if(index.good()) {
|
||||
size_t size = 0;
|
||||
index.read(reinterpret_cast<char *>(&size), sizeof(size));
|
||||
std::map<size_t, Area::params> tmp;
|
||||
while(!index.eof()) {
|
||||
area_id id = 0;
|
||||
index.read(reinterpret_cast<char *>(&id), sizeof(area_id));
|
||||
size_t id = UINT32_MAX;
|
||||
index.read(reinterpret_cast<char *>(&id), sizeof(size_t));
|
||||
Area::params params{voxel_pos(0), 0};
|
||||
index.read(reinterpret_cast<char *>(¶ms.center.x), sizeof(voxel_pos::value_type));
|
||||
index.read(reinterpret_cast<char *>(¶ms.center.y), sizeof(voxel_pos::value_type));
|
||||
index.read(reinterpret_cast<char *>(¶ms.center.z), sizeof(voxel_pos::value_type));
|
||||
index.read(reinterpret_cast<char *>(¶ms.radius), sizeof(int));
|
||||
index.read(reinterpret_cast<char *>(¶ms.seed), sizeof(int));
|
||||
auto ok = far_areas.emplace(id, params).second;
|
||||
[[maybe_unused]]
|
||||
auto ok = tmp.emplace(id, params).second;
|
||||
assert(ok && "Duplicated area");
|
||||
index.peek();
|
||||
}
|
||||
assert(far_areas.size() == size && "Corrupted areas index");
|
||||
assert(tmp.size() == size && "Corrupted areas index");
|
||||
far_areas = data::generational::vector<Area::params>(tmp);
|
||||
LOG_D(far_areas.size() << " areas loaded");
|
||||
} else {
|
||||
LOG_E("No index file!!! Probably a new world...");
|
||||
//TODO: generate universe
|
||||
far_areas.emplace(1, Area::params{voxel_pos(0), 1 << 20});
|
||||
far_areas.emplace(2, Area::params{voxel_pos(0), 1, 43});
|
||||
far_areas.emplace(Area::params{voxel_pos(0), 1 << 20});
|
||||
far_areas.emplace(Area::params{voxel_pos(0), 1, 43});
|
||||
}
|
||||
index.close();
|
||||
}
|
||||
|
@ -144,24 +147,19 @@ void Universe::saveAreas() const {
|
|||
size_t size = areas.size() + far_areas.size();
|
||||
index.write(reinterpret_cast<char *>(&size), sizeof(size));
|
||||
}
|
||||
for(const auto& area: areas) {
|
||||
auto id = area.first;
|
||||
auto params = area.second->getParams();
|
||||
index.write(reinterpret_cast<char *>(&id), sizeof(area_id));
|
||||
std::function write = [&](area_id id, Area::params params) {
|
||||
auto idx = id.index;
|
||||
index.write(reinterpret_cast<char *>(&idx), sizeof(size_t));
|
||||
index.write(reinterpret_cast<char *>(¶ms.center.x), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(¶ms.center.y), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(¶ms.center.z), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(¶ms.radius), sizeof(int));
|
||||
index.write(reinterpret_cast<char *>(¶ms.seed), sizeof(int));
|
||||
};
|
||||
for(const auto& area: areas) {
|
||||
write(area.first, area.second->getParams());
|
||||
}
|
||||
for(auto far: far_areas) {
|
||||
index.write(reinterpret_cast<char *>(&far.first), sizeof(area_id));
|
||||
index.write(reinterpret_cast<char *>(&far.second.center.x), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(&far.second.center.y), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(&far.second.center.z), sizeof(voxel_pos::value_type));
|
||||
index.write(reinterpret_cast<char *>(&far.second.radius), sizeof(int));
|
||||
index.write(reinterpret_cast<char *>(&far.second.seed), sizeof(int));
|
||||
}
|
||||
far_areas.iter(write);
|
||||
if(!index.good())
|
||||
LOG_E("Areas index write error");
|
||||
|
||||
|
@ -176,17 +174,15 @@ void Universe::update(const voxel_pos& pos, float deltaTime, Universe::report& r
|
|||
|
||||
if(chunkChange) {
|
||||
rmt_ScopedCPUSample(Far, 0);
|
||||
auto it = far_areas.begin();
|
||||
while(it != far_areas.end()) {
|
||||
const chunk_pos diff = glm::divide(pos - it->second.center);
|
||||
if (glm::length2(diff) > glm::pow2(loadDistance + it->second.radius)) {
|
||||
it++;
|
||||
} else {
|
||||
LOG_I("Load area " << it->first);
|
||||
areas.emplace(it->first, std::make_shared<Area>(it->second));
|
||||
it = far_areas.erase(it);
|
||||
}
|
||||
}
|
||||
far_areas.extract([&](area_id id, Area::params params){
|
||||
if (const chunk_pos diff = glm::divide(pos - params.center);
|
||||
glm::length2(diff) > glm::pow2(loadDistance + params.radius))
|
||||
return false;
|
||||
|
||||
LOG_I("Load area " << id.index);
|
||||
areas.emplace(id, std::make_shared<Area>(params));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
{ // Update alive areas
|
||||
rmt_ScopedCPUSample(Update, 0);
|
||||
|
@ -197,7 +193,7 @@ void Universe::update(const voxel_pos& pos, float deltaTime, Universe::report& r
|
|||
auto it = areas.begin();
|
||||
while (it != areas.end()) {
|
||||
rmt_ScopedCPUSample(Area, 0);
|
||||
const bool chunkChangeArea = (it->first == 2 && it->second->move(glm::vec3(deltaTime))) || chunkChange; // TODO: area.velocity
|
||||
const bool chunkChangeArea = (false && it->first == 1 && it->second->move(glm::vec3(deltaTime))) || chunkChange; // TODO: area.velocity
|
||||
const chunk_pos diff = glm::divide(pos - it->second->getOffset().as_voxel());
|
||||
auto &chunks = it->second->setChunks();
|
||||
if (glm::length2(diff) > glm::pow2(keepDistance + it->second->getChunks().getRadius())) {
|
||||
|
@ -206,8 +202,10 @@ void Universe::update(const voxel_pos& pos, float deltaTime, Universe::report& r
|
|||
saveQueue.emplace(*it, *it_c);
|
||||
it_c = chunks.erase(it_c);
|
||||
}
|
||||
LOG_I("Remove area " << it->first);
|
||||
far_areas.emplace(it->first, it->second->getParams());
|
||||
LOG_I("Unload area " << it->first.index);
|
||||
[[maybe_unused]]
|
||||
auto ok = far_areas.put(it->first, it->second->getParams());
|
||||
assert(ok);
|
||||
it = areas.erase(it);
|
||||
saveAreas();
|
||||
} else {
|
||||
|
@ -224,7 +222,7 @@ void Universe::update(const voxel_pos& pos, float deltaTime, Universe::report& r
|
|||
const area_<chunk_pos> acPos = std::make_pair(it->first, it_c->first);
|
||||
if (const auto neighbors = it_c->second->update()) {
|
||||
contouring->onUpdate(acPos, diff, chunks, neighbors.value());
|
||||
} else if (chunkChange || it->first == 2) {
|
||||
} else if (chunkChangeArea) {
|
||||
contouring->onNotify(acPos, diff, chunks);
|
||||
}
|
||||
++it_c;
|
||||
|
|
|
@ -35,13 +35,13 @@ namespace world {
|
|||
/// Reports to UI
|
||||
struct report {
|
||||
/// Chunks in memory
|
||||
circular_buffer<float> chunk_count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
report_buffer chunk_count;
|
||||
/// Loaded chunks
|
||||
circular_buffer<float> chunk_load = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
report_buffer chunk_load;
|
||||
/// Saved chunks
|
||||
circular_buffer<float> chunk_unload = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
report_buffer chunk_unload;
|
||||
/// Regions in memory
|
||||
circular_buffer<float> region_count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
report_buffer region_count;
|
||||
};
|
||||
|
||||
Universe(const options &);
|
||||
|
@ -80,7 +80,7 @@ namespace world {
|
|||
area_map areas;
|
||||
using area_it_t = robin_hood::pair<area_id, std::shared_ptr<Area>>;
|
||||
/// Dead areas
|
||||
robin_hood::unordered_flat_map<area_id, Area::params> far_areas;
|
||||
data::generational::vector<Area::params> far_areas;
|
||||
void saveAreas() const;
|
||||
|
||||
bool running = true;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include "../data/glm.hpp"
|
||||
#include "../data/generational.hpp"
|
||||
|
||||
const auto CHUNK_LENGTH = glm::IDX_LENGTH;
|
||||
const auto REGION_LENGTH = glm::IDX_LENGTH;
|
||||
|
@ -33,7 +34,7 @@ using region_pos = glm::ivec3;
|
|||
using region_chunk_pos = glm::ucvec3;
|
||||
using region_chunk_idx = glm::u16;
|
||||
|
||||
using area_id = uint64_t;
|
||||
using area_id = data::generational::id;
|
||||
template <class pos>
|
||||
using area_ = std::pair<area_id, pos>;
|
||||
struct area_hash {
|
||||
|
@ -45,6 +46,5 @@ struct area_hash {
|
|||
}
|
||||
};
|
||||
using area_pos = glm::ifvec3;
|
||||
using entity_id = uint64_t;
|
||||
|
||||
using camera_pos = glm::ifvec3;
|
||||
|
|
|
@ -7,7 +7,7 @@ using namespace world;
|
|||
#define REMOVE_CORRUPTED 1
|
||||
|
||||
FileRegion::FileRegion(const std::string &folderPath, const area_<region_pos> &pos) {
|
||||
path = folderPath + '/' + std::to_string(pos.first) + '.' + std::to_string(pos.second.x) + '.' +
|
||||
path = folderPath + '/' + std::to_string(pos.first.index) + '.' + std::to_string(pos.second.x) + '.' +
|
||||
std::to_string(pos.second.y) + '.' + std::to_string(pos.second.z) + ".map";
|
||||
|
||||
load();
|
||||
|
|
|
@ -6,7 +6,7 @@ using namespace world;
|
|||
#define LAZYNESS 8
|
||||
|
||||
MemoryRegion::MemoryRegion(const std::string &folderPath, const area_<region_pos> &pos) {
|
||||
path = folderPath + '/' + std::to_string(pos.first) + '.' + std::to_string(pos.second.x) + '.' +
|
||||
path = folderPath + '/' + std::to_string(pos.first.index) + '.' + std::to_string(pos.second.x) + '.' +
|
||||
std::to_string(pos.second.y) + '.' + std::to_string(pos.second.z) + ".map";
|
||||
|
||||
load();
|
||||
|
|
Loading…
Reference in New Issue