2020-07-10 17:49:16 +00:00
|
|
|
#include "World.hpp"
|
|
|
|
|
2020-07-14 17:03:32 +00:00
|
|
|
#include "../contouring/SurrondingFlatBox.hpp"
|
2020-07-10 17:49:16 +00:00
|
|
|
#include "../render/buffer/ShortIndexedBuffer.hpp"
|
2020-07-18 12:54:07 +00:00
|
|
|
#include <Remotery.h>
|
2020-07-10 17:49:16 +00:00
|
|
|
|
|
|
|
World::World(const World::options& options) {
|
|
|
|
setOptions(options);
|
|
|
|
}
|
|
|
|
World::~World() { }
|
|
|
|
|
|
|
|
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-10 17:49:16 +00:00
|
|
|
for(auto [chunkPos, chunk]: chunks) {
|
|
|
|
const glm::ivec3 dist = last_pos - chunkPos;
|
|
|
|
if (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z > keepDistance * keepDistance
|
|
|
|
&& unloadQueue.push(chunkPos)) {
|
|
|
|
//TODO: unloadCount++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chunk->update()) { // MAYBE: update joints
|
2020-07-14 17:03:32 +00:00
|
|
|
//TODO: extract in contouring
|
|
|
|
contouring::surrounding::chunks surrounding;
|
|
|
|
surrounding[contouring::surrounding::CENTER] = chunk;
|
|
|
|
bool all_found = true;
|
|
|
|
for (size_t i = 0; all_found && i < contouring::surrounding::CENTER; i++) {
|
|
|
|
const auto it = chunks.find(chunkPos + g_face_offsets[i]);
|
|
|
|
if (it != chunks.end())
|
|
|
|
surrounding[i] = it->second;
|
|
|
|
else
|
|
|
|
all_found = false;
|
|
|
|
}
|
|
|
|
if(all_found) {
|
2020-07-18 12:54:07 +00:00
|
|
|
rmt_ScopedCPUSample(Render, 0);
|
2020-07-14 17:03:32 +00:00
|
|
|
if (chunk->buffer != NULL)
|
|
|
|
delete chunk->buffer;
|
2020-07-10 17:49:16 +00:00
|
|
|
|
2020-07-14 17:03:32 +00:00
|
|
|
std::vector<VertexData> vertices;
|
2020-07-18 12:54:07 +00:00
|
|
|
{
|
|
|
|
rmt_ScopedCPUSample(Contouring, 0);
|
|
|
|
SurrondingFlatBox::render(surrounding, vertices);
|
|
|
|
}
|
|
|
|
ShortIndexedBuffer::Data data(vertices); // NOTE: indexing is really slow
|
|
|
|
{
|
|
|
|
rmt_ScopedCPUSample(Uploading, 0);
|
|
|
|
chunk->buffer = new ShortIndexedBuffer(GL_TRIANGLES, data);
|
|
|
|
}
|
2020-07-14 17:03:32 +00:00
|
|
|
}
|
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);
|
|
|
|
for (size_t i = 0; i < 8 && !unloadQueue.empty(); i++) {
|
|
|
|
chunks.extract(unloadQueue.pop());
|
|
|
|
//TODO: save to file
|
|
|
|
}
|
2020-07-10 17:49:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find missing chunks (~240ms from max loadDistance)
|
|
|
|
if(chunkChange) {
|
2020-07-18 12:54:07 +00:00
|
|
|
rmt_ScopedCPUSample(ToLoad, 0);
|
2020-07-10 17:49:16 +00:00
|
|
|
std::vector<chunk_pos> to_load;
|
|
|
|
for (int x = -loadDistance; x <= loadDistance; x++) {
|
|
|
|
for (int y = -loadDistance; y <= loadDistance; y++) {
|
|
|
|
for (int z = -loadDistance; z <= loadDistance; z++) {
|
|
|
|
if (x * x + y * y + z * z <= loadDistance * loadDistance) {
|
|
|
|
const chunk_pos p = last_pos + glm::ivec3(x, y, z);
|
|
|
|
if (chunks.find(p) == chunks.end()) {
|
|
|
|
to_load.push_back(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}}
|
|
|
|
std::sort(to_load.begin(), to_load.end(), [](const chunk_pos &a, const chunk_pos &b) {
|
|
|
|
return glm::length2(a) < glm::length2(b);
|
|
|
|
});
|
|
|
|
for(auto p: to_load) {
|
|
|
|
loadQueue.push(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rep.chunk_load.push(loadQueue.size());
|
|
|
|
// Load chunks
|
2020-07-18 12:54:07 +00:00
|
|
|
{
|
|
|
|
rmt_ScopedCPUSample(Load, 0);
|
|
|
|
for (size_t i = 0; i < 8 && !loadQueue.empty(); i++) {
|
|
|
|
const auto pos = loadQueue.pop();
|
|
|
|
const auto chunk = std::make_shared<Chunk>(pos, generator);
|
|
|
|
chunks.insert({pos, chunk});
|
|
|
|
//trigger surronding render
|
|
|
|
for (size_t i = 0; i < contouring::surrounding::CENTER; i++) {
|
|
|
|
const auto it = chunks.find(pos + g_face_offsets[i]);
|
|
|
|
if (it != chunks.end())
|
|
|
|
it->second->invalidate();
|
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void World::getModels(std::vector<std::pair<glm::mat4, Buffer*>> &out, float scale) const {
|
|
|
|
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(scale));
|
|
|
|
for(const auto [pos, chunk]: chunks) {
|
|
|
|
if(chunk->buffer != NULL)
|
|
|
|
out.push_back({glm::translate(scaling, glm::vec3(pos) * glm::vec3(CHUNK_LENGTH)), chunk->buffer});
|
|
|
|
}
|
|
|
|
}
|
2020-07-10 19:37:49 +00:00
|
|
|
void World::getModels(std::vector<std::pair<glm::mat4, Buffer*>> &out, float scale, const Frustum& frustum) const {
|
|
|
|
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(scale));
|
|
|
|
for(const auto [pos, chunk]: chunks) {
|
|
|
|
if(chunk->buffer != NULL && frustum.contains(Box::fromMin(scale * glm::vec3(pos) * glm::vec3(CHUNK_LENGTH), scale * glm::vec3(CHUNK_LENGTH))))
|
|
|
|
out.push_back({glm::translate(scaling, glm::vec3(pos) * glm::vec3(CHUNK_LENGTH)), chunk->buffer});
|
|
|
|
}
|
|
|
|
}
|