1
0
Fork 0
Univerxel/src/world/World.cpp

116 lines
3.7 KiB
C++
Raw Normal View History

2020-07-10 17:49:16 +00:00
#include "World.hpp"
2020-07-18 15:42:45 +00:00
#include "../contouring/Dummy.hpp"
2020-07-18 12:54:07 +00:00
#include <Remotery.h>
2020-07-10 17:49:16 +00:00
2020-07-22 20:55:13 +00:00
World::World(const World::options &options): loadPool(2), contouring(std::make_shared<contouring::Dummy>()) {
2020-07-10 17:49:16 +00:00
setOptions(options);
}
2020-07-18 15:42:45 +00:00
World::~World() {
contouring = NULL;
}
2020-07-10 17:49:16 +00:00
2020-07-22 20:55:13 +00:00
World::LoadPool::LoadPool(size_t count) {
for (size_t i = 0; i < count; i++) {
workers.push_back(std::thread([&] {
while (running) {
chunk_pos ctx;
loadQueue.wait();
if (loadQueue.pop(ctx)) {
rmt_ScopedCPUSample(ProcessGenerate, 0);
loadedQueue.push({ctx, std::make_shared<Chunk>(ctx, generator)});
}
}
}));
}
}
World::LoadPool::~LoadPool() {
running = false;
loadQueue.notify();
for (auto &worker : workers) {
if (worker.joinable())
worker.join();
}
}
inline void World::LoadPool::push(const chunk_pos &pos, int weight) { loadQueue.push(pos, weight); }
2020-07-23 19:39:08 +00:00
inline bool World::LoadPool::pop(robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> &out) { return loadedQueue.pop(out); }
2020-07-22 20:55:13 +00:00
inline size_t World::LoadPool::size() { return loadQueue.size(); }
2020-07-10 17:49:16 +00:00
void World::update(const camera_pos& pos, World::report& rep) {
const chunk_pos newPos = glm::divide(pos, chunk_voxel_pos(CHUNK_LENGTH));
const auto chunkChange = newPos != last_pos;
last_pos = newPos;
2020-07-18 12:54:07 +00:00
rmt_ScopedCPUSample(World, 0);
2020-07-10 17:49:16 +00:00
// Update alive chunks
{
2020-07-18 12:54:07 +00:00
rmt_ScopedCPUSample(Update, 0);
2020-07-22 20:55:13 +00:00
for (auto &[chunkPos, chunk]: chunks) {
2020-07-18 15:42:45 +00:00
if (glm::length2(last_pos - chunkPos) > keepDistance * keepDistance
2020-07-10 17:49:16 +00:00
&& unloadQueue.push(chunkPos)) {
//TODO: unloadCount++;
continue;
}
2020-07-18 15:42:45 +00:00
if (chunk->update()) { // MAYBE: also contour joints
2020-07-22 20:55:13 +00:00
contouring->onUpdate(chunkPos, chunks, Faces::None); //TODO: get update update_type(simple(pos), complex)
2020-07-18 15:42:45 +00:00
} else if (chunkChange) { //NOTE: must be solved before octrees
contouring->onNotify(chunkPos, chunks);
2020-07-10 17:49:16 +00:00
}
}
}
2020-07-22 20:55:13 +00:00
{
rmt_ScopedCPUSample(Contouring, 0);
contouring->update(pos);
}
2020-07-10 17:49:16 +00:00
rep.chunk_unload.push(unloadQueue.size());
// Unload dead chunks
2020-07-18 12:54:07 +00:00
{
rmt_ScopedCPUSample(Unload, 0);
2020-07-24 19:42:47 +00:00
for (size_t i = 0; i < 256 && !unloadQueue.empty(); i++) {
2020-07-23 19:39:08 +00:00
chunks.erase(unloadQueue.pop());
2020-07-18 12:54:07 +00:00
//TODO: save to file
}
2020-07-10 17:49:16 +00:00
}
2020-07-22 20:55:13 +00:00
// Find missing chunks
2020-07-10 17:49:16 +00:00
if(chunkChange) {
2020-07-18 12:54:07 +00:00
rmt_ScopedCPUSample(ToLoad, 0);
2020-07-22 20:55:13 +00:00
//TODO: circle point algo
2020-07-10 17:49:16 +00:00
for (int x = -loadDistance; x <= loadDistance; x++) {
for (int y = -loadDistance; y <= loadDistance; y++) {
for (int z = -loadDistance; z <= loadDistance; z++) {
2020-07-22 20:55:13 +00:00
const auto dist2 = x * x + y * y + z * z;
if (dist2 <= loadDistance * loadDistance) {
2020-07-10 17:49:16 +00:00
const chunk_pos p = last_pos + glm::ivec3(x, y, z);
if (chunks.find(p) == chunks.end()) {
2020-07-22 20:55:13 +00:00
loadPool.push(p, -dist2);
2020-07-10 17:49:16 +00:00
}
}
}}}
}
2020-07-22 20:55:13 +00:00
rep.chunk_load.push(loadPool.size());
// Loaded chunks
2020-07-18 12:54:07 +00:00
{
rmt_ScopedCPUSample(Load, 0);
2020-07-23 19:39:08 +00:00
robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> loaded;
2020-07-22 20:55:13 +00:00
while (loadPool.pop(loaded)) {
chunks.insert(loaded);
contouring->onUpdate(loaded.first, chunks, Faces::All);
2020-07-14 17:03:32 +00:00
}
2020-07-10 17:49:16 +00:00
}
rep.chunk_count.push(chunks.size());
}
void World::setOptions(const World::options& options) {
loadDistance = options.loadDistance;
keepDistance = options.keepDistance;
}
2020-07-18 15:42:45 +00:00
void World::setContouring(std::shared_ptr<contouring::Abstract> ct) {
contouring = ct;
last_pos = chunk_pos(INT_MAX); // trigger chunkChange on next update
2020-07-10 19:37:49 +00:00
}