Commit 8d0c9194 authored by Shu's avatar Shu 🍠
Browse files

Areas onload and index

parent a05378c2
......@@ -16,8 +16,8 @@
- [x] Unload unused
- [x] Edition
- [ ] Entity
- [ ] Area
- [ ] Offset
- [x] Area
- [x] Offset
- [ ] Rotation
- [ ] Planet
- [ ] CubicSphere
......
......@@ -2,7 +2,12 @@
#include "math.hpp"
using namespace glm;
ifvec3::ifvec3(const llvec3 &pos, int density) : raw(divide(pos, uvec3(IDX_LENGTH2 * density))), offset(0) {}
ifvec3::ifvec3(const llvec3 &pos, uint density) {
const auto d = IDX_LENGTH2 * density;
raw = divide(pos, glm::uvec3(d));
offset = glm::vec3(rem(pos.x, d), rem(pos.y, d), rem(pos.z, d));
if(density > 1) center();
}
llvec3 ifvec3::raw_as_long() const {
return llvec3(raw) * llvec3(IDX_LENGTH2);
}
......
......@@ -23,7 +23,7 @@ namespace glm {
ifvec3(const raw_t &raw, const offset_t &offset, bool recenter = true) : raw(raw), offset(offset) {
if(recenter) center();
}
ifvec3(const glm::llvec3 &pos, int density = 1);
ifvec3(const glm::llvec3 &pos, uint density = 1);
raw_t raw;
offset_t offset;
......
......@@ -31,8 +31,14 @@ namespace world {
public:
using regions_t = robin_hood::unordered_map<region_pos, std::shared_ptr<Region>>;
struct params {
voxel_pos center;
int radius;
int seed = 42;
};
/// radius: size in chunk (length = radius * 2 + 1)
Area(const area_pos& center, int radius, int seed = 42): center(center), chunks(radius), generator(seed) { }
Area(const params& p): center(p.center), chunks(p.radius), generator(p.seed) { }
inline const area_pos &getOffset() const { return center; }
inline geometry::IBox getBounding() const {
......@@ -55,6 +61,8 @@ namespace world {
inline Generator &getGenerator() { return generator; }
inline params getParams() const { return params{center.as_voxel(), chunks.getRadius(), generator.getSeed()}; }
private:
area_pos center;
......
......@@ -18,7 +18,7 @@ namespace world {
#else
using noise = FastNoiseSIMD *;
#endif
Generator(int seed = 42) {
Generator(int seed = 42): seed(seed) {
#if HASTY
printf("double!!!\n");
const size_t fastestSimd = HastyNoise::GetFastestSIMD();
......@@ -65,7 +65,10 @@ namespace world {
#endif
}
private:
inline int getSeed() const { return seed; }
private:
int seed;
noise densityNoise;
noise materialNoise;
};
......
......@@ -8,7 +8,7 @@
using namespace world;
const auto MAIN_AREA = 1;
const auto AREAS_FILE = "/areas.idx";
Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"), contouring(std::make_shared<contouring::Dummy>()) {
setOptions(options);
......@@ -21,8 +21,34 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
running = true;
std::filesystem::create_directories(folderPath);
//areas.emplace(MAIN_AREA, std::make_shared<Area>(area_pos(glm::multiply(chunk_pos(1 << 8, 0, 0))), 1 << 20));
areas.emplace(2, std::make_shared<Area>(area_pos(voxel_pos(0)), 1 << 20));
{
std::ifstream index(folderPath + AREAS_FILE);
if(index.good()) {
size_t size = 0;
index.read(reinterpret_cast<char *>(&size), sizeof(size));
while(!index.eof()) {
area_id id = 0;
index.read(reinterpret_cast<char *>(&id), sizeof(area_id));
Area::params params{voxel_pos(0), 0};
index.read(reinterpret_cast<char *>(&params.center.x), sizeof(voxel_pos::value_type));
index.read(reinterpret_cast<char *>(&params.center.y), sizeof(voxel_pos::value_type));
index.read(reinterpret_cast<char *>(&params.center.z), sizeof(voxel_pos::value_type));
index.read(reinterpret_cast<char *>(&params.radius), sizeof(int));
index.read(reinterpret_cast<char *>(&params.seed), sizeof(int));
auto ok = far_areas.emplace(id, params).second;
assert(ok && "Duplicated area");
index.peek();
}
assert(far_areas.size() == size && "Corrupted areas index");
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});
}
index.close();
}
// Load workers
for (size_t i = 0; i < 4; i++) {
......@@ -90,6 +116,7 @@ Universe::~Universe() {
} while (size > 0);
std::cout << std::endl;
}
saveAreas();
running = false;
loadQueue.notify();
......@@ -106,12 +133,61 @@ Universe::~Universe() {
LOG_D("Universe disappeared");
}
// Write areas index (warn: file io)
void Universe::saveAreas() const {
std::ofstream index(folderPath + AREAS_FILE, std::ios::out | std::ios::binary);
if(!index.good()) {
LOG_E("Areas index write error");
return;
}
{
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));
index.write(reinterpret_cast<char *>(&params.center.x), sizeof(voxel_pos::value_type));
index.write(reinterpret_cast<char *>(&params.center.y), sizeof(voxel_pos::value_type));
index.write(reinterpret_cast<char *>(&params.center.z), sizeof(voxel_pos::value_type));
index.write(reinterpret_cast<char *>(&params.radius), sizeof(int));
index.write(reinterpret_cast<char *>(&params.seed), sizeof(int));
}
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));
}
if(!index.good())
LOG_E("Areas index write error");
index.close();
}
void Universe::update(const voxel_pos& pos, float deltaTime, Universe::report& rep) {
rmt_ScopedCPUSample(Universe, 0);
const chunk_pos newPos = glm::divide(pos);
const auto chunkChange = last_pos != newPos;
last_pos = newPos;
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);
}
}
}
{ // Update alive areas
rmt_ScopedCPUSample(Update, 0);
size_t chunk_count = 0;
......@@ -130,7 +206,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());
it = areas.erase(it);
saveAreas();
} else {
bool lazyArea = queuesEmpty;
{ // Update alive chunks
......
......@@ -79,8 +79,9 @@ namespace world {
/// Alive areas containing chunks
area_map areas;
using area_it_t = robin_hood::pair<area_id, std::shared_ptr<Area>>;
//TODO: far_areas: <pos, {id, size, seed}>
/// Dead areas
robin_hood::unordered_flat_map<area_id, Area::params> far_areas;
void saveAreas() const;
bool running = true;
std::vector<std::thread> loadWorkers;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment