#include "FlatSurroundingBox.hpp" #include "boxing.hpp" #include "../world/Chunk.hpp" #include #include 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 ctx; loadQueue.wait(); if (loadQueue.pop(ctx)) { rmt_ScopedCPUSample(ProcessContouring, 0); std::vector 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> &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> &data, Faces neighbors) { enqueue(pos, data); if (neighbors && Faces::Right) enqueue(pos + g_face_offsets[static_cast(Face::Right)], data); if (neighbors && Faces::Left) enqueue(pos + g_face_offsets[static_cast(Face::Left)], data); if (neighbors && Faces::Up) enqueue(pos + g_face_offsets[static_cast(Face::Up)], data); if (neighbors && Faces::Down) enqueue(pos + g_face_offsets[static_cast(Face::Down)], data); if (neighbors && Faces::Forward) enqueue(pos + g_face_offsets[static_cast(Face::Forward)], data); if (neighbors && Faces::Backward) enqueue(pos + g_face_offsets[static_cast(Face::Backward)], data); } void FlatSurroundingBox::onNotify(const chunk_pos &pos, const robin_hood::unordered_map> &data) { if (buffers.find(pos) == buffers.end()) { enqueue(pos, data); } } void FlatSurroundingBox::update(const camera_pos& pos) { AbstractFlat::update(pos); std::pair 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 &idx) { return surrounding[idx.first]->get(idx.second).Density < UCHAR_MAX; // MAYBE: materials::transparent } void FlatSurroundingBox::render(const surrounding::faces &surrounding, std::vector &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)); } } } }