127 lines
5.6 KiB
C++
127 lines
5.6 KiB
C++
#include "FlatSurroundingBox.hpp"
|
|
|
|
#include "boxing.hpp"
|
|
#include "../world/Chunk.hpp"
|
|
#include <Remotery.h>
|
|
#include <imgui.h>
|
|
|
|
using namespace geometry;
|
|
namespace contouring {
|
|
FlatSurroundingBox::FlatSurroundingBox(const std::string &opt) : AbstractFlat(opt) {
|
|
for (size_t i = 1; i <= 4; i++) {
|
|
workers.push_back(std::thread([&] {
|
|
while (running) {
|
|
std::pair<chunk_pos, surrounding::faces> ctx;
|
|
loadQueue.wait();
|
|
if (loadQueue.pop(ctx)) {
|
|
rmt_ScopedCPUSample(ProcessContouring, 0);
|
|
std::vector<buffer::VertexData> vertices;
|
|
render(ctx.second, vertices);
|
|
{
|
|
rmt_ScopedCPUSample(Index, 0);
|
|
loadedQueue.push({ctx.first, buffer::ShortIndexed::Data(vertices)});
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
FlatSurroundingBox::~FlatSurroundingBox() {
|
|
running = false;
|
|
loadQueue.notify();
|
|
|
|
for(auto& worker: workers) {
|
|
if (worker.joinable())
|
|
worker.join();
|
|
}
|
|
}
|
|
|
|
void FlatSurroundingBox::enqueue(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data) {
|
|
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
|
|
const auto dist2 = glm::length2(pos - center);
|
|
if (dist2 <= loadDistance * loadDistance) {
|
|
surrounding::faces surrounding;
|
|
if(surrounding::load(surrounding, pos, data)) {
|
|
loadQueue.push(pos, surrounding, -dist2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FlatSurroundingBox::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data, Faces neighbors) {
|
|
enqueue(pos, data);
|
|
if (neighbors && Faces::Right)
|
|
enqueue(pos + g_face_offsets[static_cast<int>(Face::Right)], data);
|
|
|
|
if (neighbors && Faces::Left)
|
|
enqueue(pos + g_face_offsets[static_cast<int>(Face::Left)], data);
|
|
|
|
if (neighbors && Faces::Up)
|
|
enqueue(pos + g_face_offsets[static_cast<int>(Face::Up)], data);
|
|
|
|
if (neighbors && Faces::Down)
|
|
enqueue(pos + g_face_offsets[static_cast<int>(Face::Down)], data);
|
|
|
|
if (neighbors && Faces::Forward)
|
|
enqueue(pos + g_face_offsets[static_cast<int>(Face::Forward)], data);
|
|
|
|
if (neighbors && Faces::Backward)
|
|
enqueue(pos + g_face_offsets[static_cast<int>(Face::Backward)], data);
|
|
}
|
|
|
|
void FlatSurroundingBox::onNotify(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data) {
|
|
if (buffers.find(pos) == buffers.end()) {
|
|
enqueue(pos, data);
|
|
}
|
|
}
|
|
|
|
void FlatSurroundingBox::update(const camera_pos& pos) {
|
|
AbstractFlat::update(pos);
|
|
std::pair<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);
|
|
const auto it = buffers.find(out.first);
|
|
if (it != buffers.end()) {
|
|
if(it->second != NULL)
|
|
delete it->second;
|
|
|
|
it->second = buffer;
|
|
} else {
|
|
buffers.emplace(out.first, buffer);
|
|
}
|
|
}
|
|
reports.count.push(buffers.size());
|
|
}
|
|
|
|
void FlatSurroundingBox::onGui() {
|
|
ImGui::PlotHistogram("Count", reports.count.buffer.get(), reports.count.size, 0, std::to_string(reports.count.current()).c_str(), 0);
|
|
ImGui::PlotHistogram("Loading", reports.load.buffer.get(), reports.load.size, 0, std::to_string(reports.load.current()).c_str(), 0);
|
|
ImGui::PlotHistogram("Waiting", reports.loaded.buffer.get(), reports.loaded.size, 0, std::to_string(reports.loaded.current()).c_str(), 0);
|
|
ImGui::Separator();
|
|
AbstractFlat::onGui();
|
|
}
|
|
|
|
bool FlatSurroundingBox::isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx) {
|
|
return surrounding[idx.first]->get(idx.second).Density < UCHAR_MAX; // MAYBE: materials::transparent
|
|
}
|
|
|
|
void FlatSurroundingBox::render(const surrounding::faces &surrounding, std::vector<buffer::VertexData> &vertices) {
|
|
const auto center = surrounding[surrounding::CENTER];
|
|
vertices.clear();
|
|
for (ushort i = 0; i < CHUNK_SIZE; i++) {
|
|
if (center->get(i).Density > 0) {
|
|
Faces faces = center->get(i).Density < UCHAR_MAX ? Faces::All :
|
|
(isTransparent(surrounding, surrounding::getNeighborIdx(i, Face::Right)) & Faces::Right) |
|
|
(isTransparent(surrounding, surrounding::getNeighborIdx(i, Face::Left)) & Faces::Left) |
|
|
(isTransparent(surrounding, surrounding::getNeighborIdx(i, Face::Up)) & Faces::Up) |
|
|
(isTransparent(surrounding, surrounding::getNeighborIdx(i, Face::Down)) & Faces::Down) |
|
|
(isTransparent(surrounding, surrounding::getNeighborIdx(i, Face::Forward)) & Faces::Forward) |
|
|
(isTransparent(surrounding, surrounding::getNeighborIdx(i, Face::Backward)) & Faces::Backward);
|
|
box::addCube(vertices, world::Chunk::getPosition(i), center->get(i).Material, faces, glm::vec3(center->get(i).Density * 1.f / UCHAR_MAX));
|
|
}
|
|
}
|
|
}
|
|
}
|