Commit f7b34f74 authored by Shu's avatar Shu 🍠
Browse files

Area position

parent 5c6ccd48
......@@ -18,10 +18,11 @@ namespace contouring {
virtual void update(const voxel_pos &pos, const world::area_map &areas) = 0;
/// Chunk data change
virtual void onUpdate(const area_<chunk_pos> &pos, const world::ChunkContainer &data, geometry::Faces neighbors) = 0;
/// @param offset priority position offset
virtual void onUpdate(const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data, geometry::Faces neighbors) = 0;
/// Chunk existante ping
/// @note notify for chunks entering view while moving
virtual void onNotify(const area_<chunk_pos> &pos, const world::ChunkContainer &data) = 0;
virtual void onNotify(const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data) = 0;
/// Display ImGui config
virtual void onGui() = 0;
/// Get options
......
......@@ -3,34 +3,40 @@
#include <imgui.h> // NOLINT
#include <toml.h>
#include "../world/Chunk.hpp"
#include "../world/Area.hpp"
namespace contouring {
void AbstractFlat::update(const voxel_pos& pos, const world::area_map& areas) {
center = glm::divide(pos);
size_t AbstractFlat::clear(const voxel_pos& pos, const world::area_map& areas) {
size_t buffer_count = 0;
auto it_a = buffers.begin();
while (it_a != buffers.end()) { // Remove out of range buffers
if (const auto area = areas.find(it_a->first); area != areas.end()) {
//Update
auto it = it_a->second.begin();
while(it != it_a->second.end()) {
if (inKeepRange(it->first /*TODO: + area.second->getPosition() */)) {
++it;
} else {
const auto& offset = it_a->second.first = area->second->getOffset();
const auto center = glm::divide(pos - offset);
auto &bfs = it_a->second.second;
auto it = bfs.begin();
while(it != bfs.end()) {
if (glm::length2(center - it->first) > glm::pow2(keepDistance)) {
if(it->second != NULL)
delete it->second;
it = it_a->second.erase(it);
it = bfs.erase(it);
} else {
buffer_count++;
++it;
}
}
++it_a;
} else {
for(auto& buffer: it_a->second) {
for(auto& buffer: it_a->second.second) {
if(buffer.second != NULL)
delete buffer.second;
}
it_a = buffers.erase(it_a);
}
}
return buffer_count;
}
AbstractFlat::AbstractFlat(const std::string& str): Abstract() {
......@@ -54,9 +60,9 @@ namespace contouring {
void AbstractFlat::getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &out, const std::optional<geometry::Frustum> &frustum, const glm::llvec3& offset, int density) {
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(1.f / density));
for (const auto [_, bfs] : buffers) {
for (const auto [pos, buffer] : bfs) {
const glm::vec3 fPos = glm::vec3(glm::multiply(pos /*TODO: + area.position*/) - offset * glm::llvec3(density)) / glm::vec3(density);
for (const auto [_, area] : buffers) {
for (const auto [pos, buffer] : area.second) {
const glm::vec3 fPos = glm::vec3(area.first + glm::multiply(pos) - offset * glm::llvec3(density)) / glm::vec3(density);
if (buffer != NULL && (!frustum.has_value() || frustum.value().contains(geometry::Box::fromMin(fPos, glm::vec3(CHUNK_LENGTH / (float)density)))))
out.emplace_back(glm::translate(scaling, fPos * (float)density), buffer);
}}
......
......@@ -10,9 +10,6 @@ namespace contouring {
AbstractFlat(const std::string &str);
virtual ~AbstractFlat() {}
/// Each frame ping. Used to clear out of range
void update(const voxel_pos &, const world::area_map &areas) override;
/// Display ImGui config
void onGui() override;
......@@ -23,16 +20,10 @@ namespace contouring {
void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &out, const std::optional<geometry::Frustum> &frustum, const glm::llvec3& offset, int density) override;
protected:
bool inline inLoadRange(const chunk_pos& point) const {
return glm::length2(center - point) <= loadDistance * loadDistance;
}
bool inline inKeepRange(const chunk_pos& point) const {
return glm::length2(center - point) <= keepDistance * keepDistance;
}
size_t clear(const voxel_pos &, const world::area_map &areas);
//MAYBE: store position copy
robin_hood::unordered_flat_map<area_id, robin_hood::unordered_flat_map<chunk_pos, buffer::Abstract *>> buffers;
chunk_pos center = chunk_pos(INT_MAX);
robin_hood::unordered_flat_map<area_id, robin_hood::pair<voxel_pos, robin_hood::unordered_flat_map<chunk_pos, buffer::Abstract *>>> buffers;
int loadDistance = 3;
int keepDistance = 4;
......
......@@ -10,8 +10,8 @@ namespace contouring {
virtual ~Dummy() { }
void update(const voxel_pos &, const world::area_map &) override {}
void onUpdate(const area_<chunk_pos> &, const world::ChunkContainer &, geometry::Faces) override {}
void onNotify(const area_<chunk_pos> &, const world::ChunkContainer &) override {}
void onUpdate(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &, geometry::Faces) override {}
void onNotify(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &) override {}
void onGui() override { }
std::string getOptions() override { return ""; }
void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &, const std::optional<geometry::Frustum>&, const glm::llvec3&, int) override { }
......
......@@ -49,9 +49,9 @@ namespace contouring {
return ss.str();
}
void FlatDualMC::enqueue(const area_<chunk_pos> &pos, const world::ChunkContainer &data) {
void FlatDualMC::enqueue(const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data) {
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
const auto dist2 = glm::length2(center - pos.second); //TODO: - area.pos
const auto dist2 = glm::length2(offset - pos.second);
if (dist2 <= loadDistance * loadDistance) {
surrounding::corners surrounding;
if(surrounding::load(surrounding, pos.second, data)) {
......@@ -60,31 +60,30 @@ namespace contouring {
}
}
void FlatDualMC::onUpdate(const area_<chunk_pos> &pos, const world::ChunkContainer &data, geometry::Faces neighbors) {
enqueue(pos, data);
void FlatDualMC::onUpdate(const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data, geometry::Faces neighbors) {
enqueue(pos, offset, data);
if (neighbors && (geometry::Faces::Left | geometry::Faces::Down | geometry::Faces::Backward)) {
for (size_t i = 1; i < 8; i++) {
enqueue(std::make_pair(pos.first, pos.second - surrounding::g_corner_offsets[i]), data);
enqueue(std::make_pair(pos.first, pos.second - surrounding::g_corner_offsets[i]), offset, data);
}
}
}
void FlatDualMC::onNotify(const area_<chunk_pos> &pos, const world::ChunkContainer &data) {
void FlatDualMC::onNotify(const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data) {
const auto it = buffers.find(pos.first);
if(it == buffers.end() || it->second.find(pos.second) == it->second.end()) {
enqueue(pos, data);
if(it == buffers.end() || it->second.second.find(pos.second) == it->second.second.end()) {
enqueue(pos, offset, data);
}
}
void FlatDualMC::update(const voxel_pos& pos, const world::area_map& areas) {
AbstractFlat::update(pos, areas);
std::pair<area_<chunk_pos>, buffer::ShortIndexed::Data> out;
reports.load.push(loadQueue.size());
//MAYBE: clear out of range loadQueue.trim(keepDistance * keepDistance)
reports.loaded.push(loadedQueue.size());
while(loadedQueue.pop(out)) {
const auto buffer = new buffer::ShortIndexed(GL_TRIANGLES, out.second);
auto& bfs = buffers[out.first.first];
auto &bfs = buffers[out.first.first].second; //NOTE: buffer.first uninitialized (will be set in clear())
if (const auto it = bfs.find(out.first.second); it != bfs.end()) {
if(it->second != NULL)
delete it->second;
......@@ -94,7 +93,8 @@ namespace contouring {
bfs.emplace(out.first.second, buffer);
}
}
reports.count.push(buffers.size()); //FIXME: get from AbstractFlat
size_t count = AbstractFlat::clear(pos, areas);
reports.count.push(count);
}
void FlatDualMC::onGui() {
......
......@@ -26,10 +26,10 @@ namespace contouring {
std::string getOptions() override;
/// Chunk data change
void onUpdate(const area_<chunk_pos> &, const world::ChunkContainer &, geometry::Faces) override;
void onUpdate(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &, geometry::Faces) override;
/// Chunk existante ping
/// @note notify for chunks entering view while moving
void onNotify(const area_<chunk_pos> &, const world::ChunkContainer &) override;
void onNotify(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &) override;
protected:
safe_priority_queue_map<area_<chunk_pos>, surrounding::corners, int, area_hash> loadQueue;
......@@ -44,7 +44,7 @@ namespace contouring {
bool running = true;
std::vector<std::thread> workers;
void enqueue(const area_<chunk_pos> &, const world::ChunkContainer &);
void enqueue(const area_<chunk_pos> &, const chunk_pos &offset, const world::ChunkContainer &);
float iso = .1f;
bool manifold = true;
......
......@@ -36,9 +36,9 @@ namespace contouring {
}
}
void FlatSurroundingBox::enqueue(const area_<chunk_pos> &pos, const world::ChunkContainer &data) {
void FlatSurroundingBox::enqueue(const area_<chunk_pos> &pos, const chunk_pos& offset, const world::ChunkContainer &data) {
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
const auto dist2 = glm::length2(center - pos.second /*TODO: - area.pos */);
const auto dist2 = glm::length2(offset - pos.second);
if (dist2 <= loadDistance * loadDistance) {
surrounding::faces surrounding;
if(surrounding::load(surrounding, pos.second, data)) {
......@@ -47,43 +47,42 @@ namespace contouring {
}
}
void FlatSurroundingBox::onUpdate(const area_<chunk_pos> &pos, const world::ChunkContainer &data, Faces neighbors) {
enqueue(pos, data);
void FlatSurroundingBox::onUpdate(const area_<chunk_pos> &pos, const chunk_pos& offset, const world::ChunkContainer &data, Faces neighbors) {
enqueue(pos, offset, data);
if (neighbors && Faces::Right)
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Right)]), data);
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Right)]), offset, data);
if (neighbors && Faces::Left)
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Left)]), data);
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Left)]), offset, data);
if (neighbors && Faces::Up)
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Up)]), data);
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Up)]), offset, data);
if (neighbors && Faces::Down)
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Down)]), data);
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Down)]), offset, data);
if (neighbors && Faces::Forward)
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Forward)]), data);
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Forward)]), offset, data);
if (neighbors && Faces::Backward)
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Backward)]), data);
enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast<int>(Face::Backward)]), offset, data);
}
void FlatSurroundingBox::onNotify(const area_<chunk_pos> &pos, const world::ChunkContainer &data) {
void FlatSurroundingBox::onNotify(const area_<chunk_pos> &pos, const chunk_pos& offset, const world::ChunkContainer &data) {
const auto it = buffers.find(pos.first);
if(it == buffers.end() || it->second.find(pos.second) == it->second.end()) {
enqueue(pos, data);
if(it == buffers.end() || it->second.second.find(pos.second) == it->second.second.end()) {
enqueue(pos, offset, data);
}
}
void FlatSurroundingBox::update(const voxel_pos& pos, const world::area_map& areas) {
AbstractFlat::update(pos, areas);
std::pair<area_<chunk_pos>, buffer::ShortIndexed::Data> out;
reports.load.push(loadQueue.size());
//MAYBE: clear out of range loadQueue.trim(keepDistance * keepDistance)
reports.loaded.push(loadedQueue.size());
while(loadedQueue.pop(out)) {
const auto buffer = new buffer::ShortIndexed(GL_TRIANGLES, out.second);
auto& bfs = buffers[out.first.first];
auto& bfs = buffers[out.first.first].second; //NOTE: buffer.first uninitialized
if (const auto it = bfs.find(out.first.second); it != bfs.end()) {
if(it->second != NULL)
delete it->second;
......@@ -93,7 +92,8 @@ namespace contouring {
bfs.emplace(out.first.second, buffer);
}
}
reports.count.push(buffers.size()); //FIXME: get from AbstractFlat
size_t count = AbstractFlat::clear(pos, areas);
reports.count.push(count);
}
void FlatSurroundingBox::onGui() {
......
......@@ -24,10 +24,10 @@ namespace contouring {
void onGui() override;
/// Chunk data change
void onUpdate(const area_<chunk_pos> &, const world::ChunkContainer &, geometry::Faces) override;
void onUpdate(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &, geometry::Faces) override;
/// Chunk existante ping
/// @note notify for chunks entering view while moving
void onNotify(const area_<chunk_pos> &, const world::ChunkContainer &) override;
void onNotify(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &) override;
protected:
safe_priority_queue_map<area_<chunk_pos>, surrounding::faces, int, area_hash> loadQueue;
......@@ -42,7 +42,7 @@ namespace contouring {
bool running = true;
std::vector<std::thread> workers;
void enqueue(const area_<chunk_pos> &, const world::ChunkContainer &);
void enqueue(const area_<chunk_pos> &, const chunk_pos& offset, const world::ChunkContainer &);
private:
static inline bool isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx);
......
#pragma once
#include <glm/glm.hpp>
#include <iostream>
namespace geometry {
/// Axis Aligned Floating Box
......
#pragma once
#include <glm/glm.hpp>
namespace geometry {
/// Axis Aligned Long Box
struct IBox {
using pos_t = glm::llvec3;
enum class ContainmentType {
Disjoint = false, Intersects, Contains
};
IBox(pos_t min, pos_t max): Min(min), Max(max) {
assert((max.x >= min.x && max.y >= min.y && max.z >= min.z) && "Min > Max");
}
inline static IBox fromCenter(pos_t center, pos_t::value_type radius) { return IBox(center - radius, center + radius); }
inline static IBox fromMin(pos_t min, pos_t size) { return IBox(min, min + size); }
pos_t Min;
pos_t Max;
ContainmentType contains(const IBox& box) const {
//test if all corner is in the same side of a face by just checking min and max
if (box.Max.x < Min.x
|| box.Min.x > Max.x
|| box.Max.y < Min.y
|| box.Min.y > Max.y
|| box.Max.z < Min.z
|| box.Min.z > Max.z)
return ContainmentType::Disjoint;
if (box.Min.x >= Min.x
&& box.Max.x <= Max.x
&& box.Min.y >= Min.y
&& box.Max.y <= Max.y
&& box.Min.z >= Min.z
&& box.Max.z <= Max.z)
return ContainmentType::Contains;
return ContainmentType::Intersects;
}
constexpr bool contains(const pos_t& pos) const {
return pos.x >= Min.x && pos.x <= Max.x &&
pos.y >= Min.y && pos.y <= Max.y &&
pos.z >= Min.z && pos.z <= Max.z;
}
};
}
\ No newline at end of file
#pragma once
#include "Box.hpp"
#include "IBox.hpp"
#include "../../world/position.h"
namespace geometry {
......@@ -83,5 +83,44 @@ namespace geometry {
}
points.push_back(current);
}
IBox::ContainmentType intersect(const IBox& box) const {
const glm::llvec3 start = from.as_voxel();
if(box.contains(start))
return IBox::ContainmentType::Contains;
const auto inv = 1. / glm::dvec3(dir);
glm::f64 tmin = ((inv.x < 0 ? box.Max : box.Min).x - start.x) * inv.x;
glm::f64 tmax = ((inv.x < 0 ? box.Min : box.Max).x - start.x) * inv.x;
glm::f64 tymin = ((inv.y < 0 ? box.Max : box.Min).y - start.y) * inv.y;
glm::f64 tymax = ((inv.y < 0 ? box.Min : box.Max).y - start.y) * inv.y;
if ((tmin > tymax) || (tymin > tmax)){
return IBox::ContainmentType::Disjoint;
}
if (tymin > tmin) {
tmin = tymin;
}
if (tymax < tmax){
tmax = tymax;
}
glm::f64 tzmin = ((inv.z < 0 ? box.Max : box.Min).z - start.z) * inv.z;
glm::f64 tzmax = ((inv.z < 0 ? box.Min : box.Max).z - start.z) * inv.z;
if ((tmin > tzmax) || (tzmin > tmax)){
return IBox::ContainmentType::Disjoint;
}
if (tzmin > tmin){
tmin = tzmin;
}
if (tzmax < tmax){
tmax = tzmax;
}
// this last check is different from the 'ray' case in below references:
// we need to check that the segment is on the span of the line
// that intersects the box
return tmax<0.0f || tmin> 1.0f ? IBox::ContainmentType::Intersects : IBox::ContainmentType::Disjoint;
}
};
}
......@@ -7,9 +7,12 @@ namespace glm {
constexpr ivec3 inline iround(const vec3& p) {
return ivec3(std::round<int>(p.x), std::round<int>(p.y), std::round<int>(p.z));
}
constexpr int inline length2(const ivec3& a) {
constexpr long inline length2(const ivec3& a) {
return a.x * a.x + a.y * a.y + a.z * a.z;
}
constexpr long inline pow2(int v) {
return v * v;
}
constexpr ivec3 inline diff(const ivec3& a, const ivec3& b) {
return glm::abs(glm::abs(a) - glm::abs(b));
}
......
......@@ -100,9 +100,9 @@ int main(int /*unused*/, char */*unused*/[]){
state.look_at = world.raycast(camera.getRay() * options.voxel_density);
if (state.capture_mouse && state.look_at.has_value()) {
if (inputs.isPressing(Mouse::Left))
world.setCube(state.look_at.value().first, world::Voxel(0), options.tool.radius);
world.setCube(state.look_at.value().pos, world::Voxel(0), options.tool.radius);
else if (inputs.isPressing(Mouse::Right))
world.setCube(state.look_at.value().first, world::Voxel(options.tool.material, world::Voxel::DENSITY_MAX), options.tool.radius);
world.setCube(state.look_at.value().pos, world::Voxel(options.tool.material, world::Voxel::DENSITY_MAX), options.tool.radius);
}
world.update((state.position * options.voxel_density).as_voxel(), reports.world);
inputs.saveKeys();
......@@ -171,7 +171,7 @@ int main(int /*unused*/, char */*unused*/[]){
if(state.look_at.has_value()) {
lookProgram->useIt();
lookProgram->start(renderer);
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().first.second - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.tool.radius)), glm::vec3(1 + options.tool.radius * 2));
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().pos.second + state.look_at.value().offset - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.tool.radius)), glm::vec3(1 + options.tool.radius * 2));
lookBuffer.draw(lookProgram->setup(renderer, model));
}
renderer->postProcess();
......
......@@ -166,8 +166,11 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
if (options.editor_show) {
ImGui::Begin("Editor", &options.editor_show, ImGuiWindowFlags_AlwaysAutoResize);
if (state.look_at.has_value()) {
ImGui::Text("Look at: (%ld: %lld, %lld, %lld) (%s, %.1f)", state.look_at.value().first.first, state.look_at.value().first.second.x, state.look_at.value().first.second.y, state.look_at.value().first.second.z, world::materials::textures[state.look_at.value().second.material()].c_str(), state.look_at.value().second.density() * 1. / world::Voxel::DENSITY_MAX);
ImGui::Text("(%.3f, %.3f, %.3f)", state.look_at.value().first.second.x * 1. / options.voxel_density, state.look_at.value().first.second.y * 1. / options.voxel_density, state.look_at.value().first.second.z * 1. / options.voxel_density);
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,
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);
} else {
ImGui::Text("Look at: none");
}
......
......@@ -107,7 +107,7 @@ struct options {
{"mode", contouring::names[contouring_idx]},
{"options", toml::table()}
}));
for(auto opt: contouring_data) {
for(const auto opt: contouring_data) {
if(!opt.second.empty())
config["mesh"]["options"].as_table()->insert_or_assign(opt.first, opt.second);
}
......@@ -181,7 +181,7 @@ struct options {
struct state {
bool capture_mouse = true;
camera_pos position = camera_pos(voxel_pos(0), 1);
std::optional<std::pair<area_<voxel_pos>, world::Voxel>> look_at = {};
std::optional<world::Universe::ray_target> look_at = {};
std::shared_ptr<contouring::Abstract> contouring;
......
......@@ -5,6 +5,7 @@
using namespace libguarded;
#include "region/index.hpp"
#include "Generator.hpp"
#include "../data/geometry/IBox.hpp"
namespace world {
/// Chunk map with restricted access
......@@ -13,8 +14,10 @@ namespace world {
int radius;
public:
/// Area radius in chunks
constexpr inline int getRadius() const { return radius; }
ChunkContainer(int radius): radius(radius) {
assert(radius < (1 << 22) / CHUNK_LENGTH);
assert(radius > 0 && radius < (1 << 22) / CHUNK_LENGTH);
}
inline bool inRange(const chunk_pos& pos) const {
return glm::abs(pos.x) < radius && glm::abs(pos.y) < radius && glm::abs(pos.z) < radius;
......@@ -29,16 +32,32 @@ namespace world {
using regions_t = robin_hood::unordered_map<region_pos, std::shared_ptr<Region>>;
/// radius: size in chunk (length = radius * 2 + 1)
Area(int radius, int seed = 42): chunks(radius), generator(seed) { }
Area(const voxel_pos& center, int radius, int seed = 42): center(center), chunks(radius), generator(seed) { }
inline const voxel_pos &getOffset() const { return center; }
inline geometry::IBox getBounding() const {
return geometry::IBox(center - voxel_pos(CHUNK_LENGTH * (chunks.getRadius() - 1)),
center + voxel_pos(CHUNK_LENGTH * chunks.getRadius()));
}
/// Move offset return if chunk_change
constexpr bool inline move(const voxel_pos &offset) {
const auto prev = glm::divide(center);
center += offset;
return prev != glm::divide(center);
}
inline const ChunkContainer &getChunks() const { return chunks; }
inline ChunkContainer &setChunks() { return chunks; }
std::shared_ptr<Region> getRegion(const std::string& folderPath, const area_<region_pos> &);
shared_guarded<regions_t>::handle getRegions() { return regions.lock(); }
inline Generator &getGenerator() { return generator; }
private:
//TODO: position rotation
voxel_pos center;
//TODO: rotation
ChunkContainer chunks;
shared_guarded<regions_t> regions;
......
......@@ -21,8 +21,8 @@ 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>(1 << 2));
areas.emplace(2, std::make_shared<Area>(1 << 2, 43));
areas.emplace(MAIN_AREA, std::make_shared<Area>(glm::multiply(chunk_pos(1 << 8, 0, 0)), 1 << 20));
areas.emplace(2, std::make_shared<Area>(voxel_pos(0), 1 << 20));
// Load workers
for (size_t i = 0; i < 4; i++) {
......@@ -73,18 +73,19 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
}
}
Universe::~Universe() {
contouring = NULL;
contouring = nullptr;
// Save all
for(auto& area: areas) {
for(auto& chunk: area.second->getChunks())
for(const auto& chunk: area.second->getChunks())
saveQueue.emplace(area, chunk);
}