#include "FlatSurroundingBox.hpp" #include "boxing.hpp" #include "../world/Chunk.hpp" #include // NOLINT using namespace geometry; namespace contouring { FlatSurroundingBox::FlatSurroundingBox(const std::string &opt) : AbstractFlat(opt) { for (size_t i = 1; i <= 4; i++) { workers.emplace_back([&] { while (running) { std::pair, surrounding::faces> ctx; loadQueue.wait(); if (loadQueue.pop(ctx)) { std::vector vertices; render(ctx.second, vertices); { loadedQueue.emplace(ctx.first, vertices); } } } }); } } FlatSurroundingBox::~FlatSurroundingBox() { running = false; loadQueue.notify_all(); for(auto& worker: workers) { if (worker.joinable()) worker.join(); } } void FlatSurroundingBox::enqueue(const area_ &pos, const chunk_pos& offset, const world::ChunkContainer &data) { const auto dist2 = glm::length2(offset - pos.second); if (dist2 <= loadDistance * loadDistance) { surrounding::faces surrounding; if(surrounding::load(surrounding, pos.second, data)) { loadQueue.push(pos, surrounding, -dist2); } } } void FlatSurroundingBox::onUpdate(const area_ &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(Face::Right)]), offset, data); if (neighbors && Faces::Left) enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast(Face::Left)]), offset, data); if (neighbors && Faces::Up) enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast(Face::Up)]), offset, data); if (neighbors && Faces::Down) enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast(Face::Down)]), offset, data); if (neighbors && Faces::Forward) enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast(Face::Forward)]), offset, data); if (neighbors && Faces::Backward) enqueue(std::make_pair(pos.first, pos.second + g_face_offsets[static_cast(Face::Backward)]), offset, data); } void FlatSurroundingBox::onNotify(const area_ &pos, const chunk_pos& offset, const world::ChunkContainer &data) { const auto it = buffers.find(pos.first); 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) { std::pair, buffer::ShortIndexed::Data> out; //MAYBE: clear out of range loadQueue.trim(keepDistance * keepDistance) while(loadedQueue.pop(out)) { const auto buffer = new buffer::ShortIndexed(GL_TRIANGLES, out.second); 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; it->second = buffer; } else { bfs.emplace(out.first.second, buffer); } } AbstractFlat::clear(pos, areas); } bool FlatSurroundingBox::isTransparent(const surrounding::faces &surrounding, const std::pair &idx) { return surrounding[idx.first]->get(idx.second).density() < world::Voxel::DENSITY_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 < world::CHUNK_SIZE; i++) { if (center->get(i).density() > 0) { Faces faces = center->get(i).density() < world::Voxel::DENSITY_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, glm::fromIdx(i), center->get(i).material(), faces, glm::vec3(center->get(i).density() * 1.f / world::Voxel::DENSITY_MAX)); } } } }