Extract contouring
This commit is contained in:
parent
aef06c0c39
commit
4717774885
|
@ -44,7 +44,7 @@
|
|||
{
|
||||
"label": "exec",
|
||||
"type": "shell",
|
||||
"command": "./atomic",
|
||||
"command": "./univerxel",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}/build"
|
||||
}
|
||||
|
@ -52,7 +52,7 @@
|
|||
{
|
||||
"label": "exec memcheck",
|
||||
"type": "shell",
|
||||
"command": "valgrind --leak-check=full --show-leak-kinds=all --fair-sched=yes ./atomic",
|
||||
"command": "valgrind --leak-check=full --show-leak-kinds=all --fair-sched=yes ./univerxel",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}/build"
|
||||
}
|
||||
|
@ -60,7 +60,7 @@
|
|||
{
|
||||
"label": "exec helgrind",
|
||||
"type": "shell",
|
||||
"command": "valgrind --tool=helgrind --fair-sched=yes ./atomic",
|
||||
"command": "valgrind --tool=helgrind --fair-sched=yes ./univerxel",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}/build"
|
||||
}
|
||||
|
@ -68,7 +68,7 @@
|
|||
{
|
||||
"label": "exec callgrind",
|
||||
"type": "shell",
|
||||
"command": "valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --fair-sched=yes ./atomic",
|
||||
"command": "valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --fair-sched=yes ./univerxel",
|
||||
"options": {
|
||||
"cwd": "${workspaceRoot}/build"
|
||||
}
|
||||
|
|
10
TODO.md
10
TODO.md
|
@ -17,12 +17,10 @@
|
|||
- https://imgur.com/a/bh2iy
|
||||
- https://speciesdevblog.files.wordpress.com/2012/11/biomemap.png
|
||||
- [ ] Leak test
|
||||
- https://www.deleaker.com
|
||||
- https://www.parasoft.com
|
||||
- Valgrind
|
||||
- Gprof /pprof
|
||||
- [ ] ZeroMQ
|
||||
- [ ] EnkiTS
|
||||
- [ ] Server
|
||||
- [ ] ZeroMQ
|
||||
|
||||
## Rendering
|
||||
- [x] Render triangle
|
||||
|
@ -53,4 +51,6 @@
|
|||
- [ ] Collision
|
||||
- [ ] Render with glBufferSubData
|
||||
- [x] Frustum Culling
|
||||
- [ ] Occlusion Culling
|
||||
- [ ] Occlusion Culling
|
||||
|
||||
- [ ] Document
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "../data/glm.hpp"
|
||||
#include "../render/buffer/Buffer.hpp"
|
||||
#include "../data/geometry/Frustum.hpp"
|
||||
#include <memory>
|
||||
|
||||
class World;
|
||||
class Chunk;
|
||||
namespace contouring {
|
||||
/// Generating mesh from world data
|
||||
class Abstract {
|
||||
public:
|
||||
Abstract() { }
|
||||
virtual ~Abstract() { }
|
||||
|
||||
/// Each frame ping.
|
||||
/// Mostly used for cleanup and to flush buffers data using main thread
|
||||
virtual void update(const camera_pos &pos) = 0;
|
||||
|
||||
/// Chunk data change
|
||||
virtual void onUpdate(const chunk_pos &pos, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>>& data) = 0; // TODO: get precise border data
|
||||
/// Chunk existante ping
|
||||
/// @note notify for chunks entering view while moving
|
||||
virtual void onNotify(const chunk_pos &pos, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) = 0;
|
||||
/// Display ImGui config
|
||||
virtual void onGui() = 0;
|
||||
|
||||
/// Get buffers in frustum with model matrices
|
||||
/// @note buffers invalidated after update
|
||||
virtual void getModels(std::vector<std::pair<glm::mat4, Buffer *const>> &buffers, const std::optional<Frustum>& frustum, float scale) = 0;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#include "AbstractFlat.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
#include "../world/Chunk.hpp"
|
||||
|
||||
namespace contouring {
|
||||
void AbstractFlat::update(const camera_pos& pos) {
|
||||
center = glm::divide(pos, chunk_voxel_pos(CHUNK_LENGTH));
|
||||
auto it = buffers.begin();
|
||||
while (it != buffers.end()) { // Remove out of range buffers
|
||||
if (inKeepRange(it->first)) {
|
||||
it++;
|
||||
} else {
|
||||
if(it->second != NULL)
|
||||
delete it->second;
|
||||
|
||||
it = buffers.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractFlat::onGui() {
|
||||
ImGui::SliderInt("Load Distance", &loadDistance, 1, keepDistance);
|
||||
ImGui::SliderInt("Keep Distance", &keepDistance, loadDistance+1, 21);
|
||||
}
|
||||
|
||||
void AbstractFlat::getModels(std::vector<std::pair<glm::mat4, Buffer *const>> &out, const std::optional<Frustum> &frustum, float scale) {
|
||||
const auto scaling = glm::scale(glm::mat4(1), glm::vec3(scale));
|
||||
for (const auto [pos, buffer] : buffers) {
|
||||
if (buffer != NULL && (!frustum.has_value() || frustum.value().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)), buffer});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "Abstract.hpp"
|
||||
|
||||
class World;
|
||||
class Chunk;
|
||||
namespace contouring {
|
||||
/// Generating mesh for chunks 1:1
|
||||
class AbstractFlat: public Abstract {
|
||||
public:
|
||||
AbstractFlat(): Abstract() { }
|
||||
virtual ~AbstractFlat() { }
|
||||
|
||||
/// Each frame ping. Used to clear out of range
|
||||
void update(const camera_pos &) override;
|
||||
|
||||
/// Display ImGui config
|
||||
void onGui() override;
|
||||
|
||||
/// Get buffers in frustum with model matrices
|
||||
/// @note buffers invalidated after update
|
||||
void getModels(std::vector<std::pair<glm::mat4, Buffer *const>> &out, const std::optional<Frustum> &frustum, float scale) override;
|
||||
|
||||
protected:
|
||||
bool inline inLoadRange(const chunk_pos& point) const {
|
||||
return glm::length2(center - point) <= loadDistance * loadDistance;
|
||||
}
|
||||
bool inline inKeepRange(const chunk_pos& point) const {
|
||||
return glm::length2(center - point) <= keepDistance * keepDistance;
|
||||
}
|
||||
|
||||
std::unordered_map<chunk_pos, Buffer *> buffers;
|
||||
chunk_pos center = chunk_pos(INT_MAX);
|
||||
|
||||
int loadDistance = 3; //TODO: handle config
|
||||
int keepDistance = 4;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "Abstract.hpp"
|
||||
|
||||
class World;
|
||||
class Chunk;
|
||||
namespace contouring {
|
||||
/// Useless contouring
|
||||
class Dummy: public Abstract {
|
||||
public:
|
||||
Dummy(): Abstract() { }
|
||||
virtual ~Dummy() { }
|
||||
|
||||
void update(const camera_pos &) override { }
|
||||
void onUpdate(const chunk_pos &, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override { }
|
||||
void onNotify(const chunk_pos &, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override { }
|
||||
void onGui() override { }
|
||||
void getModels(std::vector<std::pair<glm::mat4, Buffer *const>> &, const std::optional<Frustum>&, float) override { }
|
||||
};
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../world/Chunk.hpp"
|
||||
#include "boxing.hpp"
|
||||
|
||||
class FlatBox {
|
||||
public:
|
||||
FlatBox();
|
||||
~FlatBox();
|
||||
|
||||
private:
|
||||
static inline bool isTransparent(const Voxel *voxels, const std::optional<ushort>& idx) {
|
||||
return idx.has_value() ? voxels[idx.value()].Density < UCHAR_MAX : true; // MAYBE: materials::transparent
|
||||
}
|
||||
public:
|
||||
static void render(const Voxel *voxels, std::vector<VertexData> &vertices)
|
||||
{
|
||||
vertices.clear();
|
||||
for (ushort i = 0; i < CHUNK_SIZE; i++) {
|
||||
if (voxels[i].Density > 0) {
|
||||
Faces faces = voxels[i].Density < UCHAR_MAX ? Faces::All :
|
||||
(isTransparent(voxels, Chunk::getNeighborIdx(i, Face::Right)) & Faces::Right) |
|
||||
(isTransparent(voxels, Chunk::getNeighborIdx(i, Face::Left)) & Faces::Left) |
|
||||
(isTransparent(voxels, Chunk::getNeighborIdx(i, Face::Up)) & Faces::Up) |
|
||||
(isTransparent(voxels, Chunk::getNeighborIdx(i, Face::Down)) & Faces::Down) |
|
||||
(isTransparent(voxels, Chunk::getNeighborIdx(i, Face::Forward)) & Faces::Forward) |
|
||||
(isTransparent(voxels, Chunk::getNeighborIdx(i, Face::Backward)) & Faces::Backward);
|
||||
contouring::box::addCube(vertices, Chunk::getPosition(i), voxels[i].Material, faces, glm::vec3(voxels[i].Density * 1.f / UCHAR_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,74 @@
|
|||
#include "FlatSurroundingBox.hpp"
|
||||
|
||||
#include "boxing.hpp"
|
||||
#include "../render/buffer/ShortIndexedBuffer.hpp"
|
||||
#include "../world/Chunk.hpp"
|
||||
|
||||
namespace contouring {
|
||||
void FlatSurroundingBox::onUpdate(const chunk_pos &pos, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
if(!inLoadRange(pos))
|
||||
return;
|
||||
|
||||
surrounding::chunks surrounding;
|
||||
if(surrounding::load(surrounding, pos, data)) {
|
||||
std::vector<VertexData> vertices;
|
||||
render(surrounding, vertices);
|
||||
ShortIndexedBuffer::Data data(vertices);
|
||||
|
||||
const auto buffer = new ShortIndexedBuffer(GL_TRIANGLES, data);
|
||||
const auto it = buffers.find(pos);
|
||||
if (it != buffers.end()) {
|
||||
if(it->second != NULL)
|
||||
delete it->second;
|
||||
|
||||
it->second = buffer;
|
||||
} else {
|
||||
buffers.emplace(pos, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlatSurroundingBox::onNotify(const chunk_pos &pos, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
if (!inLoadRange(pos) || buffers.find(pos) != buffers.end())
|
||||
return;
|
||||
|
||||
surrounding::chunks surrounding;
|
||||
if(surrounding::load(surrounding, pos, data)) {
|
||||
std::vector<VertexData> vertices;
|
||||
render(surrounding, vertices);
|
||||
ShortIndexedBuffer::Data data(vertices);
|
||||
|
||||
const auto buffer = new ShortIndexedBuffer(GL_TRIANGLES, data);
|
||||
const auto it = buffers.find(pos);
|
||||
if (it != buffers.end()) {
|
||||
if(it->second != NULL)
|
||||
delete it->second;
|
||||
|
||||
it->second = buffer;
|
||||
} else {
|
||||
buffers.emplace(pos, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FlatSurroundingBox::isTransparent(const surrounding::chunks &surrounding, const std::pair<ushort, ushort> &idx) {
|
||||
return surrounding[idx.first]->begin()[idx.second].Density < UCHAR_MAX; // MAYBE: materials::transparent
|
||||
}
|
||||
|
||||
void FlatSurroundingBox::render(const surrounding::chunks &surrounding, std::vector<VertexData> &vertices) {
|
||||
const auto voxels = surrounding[surrounding::CENTER]->begin();
|
||||
vertices.clear();
|
||||
for (ushort i = 0; i < CHUNK_SIZE; i++) {
|
||||
if (voxels[i].Density > 0) {
|
||||
Faces faces = voxels[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, Chunk::getPosition(i), voxels[i].Material, faces, glm::vec3(voxels[i].Density * 1.f / UCHAR_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "AbstractFlat.hpp"
|
||||
#include "surrounding.hpp"
|
||||
|
||||
class VertexData;
|
||||
namespace contouring {
|
||||
class FlatSurroundingBox: public AbstractFlat {
|
||||
public:
|
||||
FlatSurroundingBox(): AbstractFlat() { }
|
||||
~FlatSurroundingBox() { }
|
||||
|
||||
/// Chunk data change
|
||||
void onUpdate(const chunk_pos &, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override;
|
||||
/// Chunk existante ping
|
||||
/// @note notify for chunks entering view while moving
|
||||
void onNotify(const chunk_pos &, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override;
|
||||
|
||||
private:
|
||||
static inline bool isTransparent(const surrounding::chunks &surrounding, const std::pair<ushort, ushort> &idx);
|
||||
static void render(const surrounding::chunks &surrounding, std::vector<VertexData> &vertices);
|
||||
};
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "chunk_surrounding.hpp"
|
||||
#include "boxing.hpp"
|
||||
using namespace contouring;
|
||||
|
||||
class SurrondingFlatBox {
|
||||
public:
|
||||
SurrondingFlatBox();
|
||||
~SurrondingFlatBox();
|
||||
|
||||
private:
|
||||
static inline bool isTransparent(const surrounding::chunks& surrounding, const std::pair<ushort, ushort>& idx) {
|
||||
return surrounding[idx.first]->begin()[idx.second].Density < UCHAR_MAX; // MAYBE: materials::transparent
|
||||
}
|
||||
public:
|
||||
static void render(const surrounding::chunks& surrounding, std::vector<VertexData> &vertices)
|
||||
{
|
||||
const auto voxels = surrounding[surrounding::CENTER]->begin();
|
||||
vertices.clear();
|
||||
for (ushort i = 0; i < CHUNK_SIZE; i++) {
|
||||
if (voxels[i].Density > 0) {
|
||||
Faces faces = voxels[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);
|
||||
contouring::box::addCube(vertices, Chunk::getPosition(i), voxels[i].Material, faces, glm::vec3(voxels[i].Density * 1.f / UCHAR_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,12 +1,25 @@
|
|||
#pragma once
|
||||
#include "surrounding.hpp"
|
||||
|
||||
#include "../world/Chunk.hpp"
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace contouring::surrounding {
|
||||
const auto CENTER = 6;
|
||||
typedef std::array<std::shared_ptr<const Chunk>, 7> chunks;
|
||||
bool load(chunks &out, const chunk_pos &chunkPos, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks) {
|
||||
{
|
||||
const auto it = chunks.find(chunkPos);
|
||||
if (it == chunks.end())
|
||||
return false;
|
||||
|
||||
out[CENTER] = it->second;
|
||||
}
|
||||
for (size_t i = 0; i < CENTER; i++) {
|
||||
const auto it = chunks.find(chunkPos + g_face_offsets[i]);
|
||||
if (it == chunks.end())
|
||||
return false;
|
||||
|
||||
out[i] = it->second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<ushort, ushort> getNeighborIdx(ushort idx, Face face) {
|
||||
switch (face) {
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
#include <memory>
|
||||
|
||||
class Chunk;
|
||||
namespace contouring::surrounding {
|
||||
const auto CENTER = 6;
|
||||
typedef std::array<std::shared_ptr<const Chunk>, CENTER+1> chunks;
|
||||
|
||||
bool load(chunks &out, const chunk_pos &chunkPos, const std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks);
|
||||
|
||||
std::pair<ushort, ushort> getNeighborIdx(ushort idx, Face face);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../glm.hpp"
|
||||
|
||||
enum class Face {
|
||||
Right, Left, Up, Down, Forward, Backward
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ class safe_unique_queue {
|
|||
private:
|
||||
std::queue<T> queue;
|
||||
std::unordered_set<T> set;
|
||||
std::mutex mutex;
|
||||
TracyLockable(std::mutex, mutex);
|
||||
std::condition_variable cv;
|
||||
|
||||
public:
|
||||
|
|
|
@ -143,6 +143,8 @@ struct state {
|
|||
camera_pos position;
|
||||
std::optional<std::pair<voxel_pos, Voxel>> look_at = {};
|
||||
|
||||
std::shared_ptr<contouring::Abstract> contouring;
|
||||
|
||||
char console_buffer[256];
|
||||
};
|
||||
|
||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "render/Renderer.hpp"
|
||||
#include "world/World.hpp"
|
||||
#include "contouring/FlatBox.hpp"
|
||||
#include "contouring/FlatSurroundingBox.hpp"
|
||||
|
||||
#include "data/state.h"
|
||||
|
||||
|
@ -49,6 +49,8 @@ int main(int, char *[]){
|
|||
renderer->LightInvDir = glm::vec3(-0.5f, 2, -2);
|
||||
|
||||
World world = World(options.world);
|
||||
world.setContouring(std::make_shared<contouring::FlatSurroundingBox>()); //FIXME: from idx
|
||||
state.contouring = world.getContouring();
|
||||
|
||||
Remotery *rmt;
|
||||
rmt_CreateGlobalInstance(&rmt);
|
||||
|
@ -113,6 +115,12 @@ int main(int, char *[]){
|
|||
if(actions && UI::Actions::Camera) {
|
||||
camera.setOptions(options.camera);
|
||||
}
|
||||
if(actions && UI::Actions::ChangeContouring) {
|
||||
state.contouring = NULL;
|
||||
//TODO: save options
|
||||
//FIXME: world.setContouring(from options.contouring_idx)
|
||||
//state.contouring = world.getContouring();
|
||||
}
|
||||
renderer->SkyEnable = options.renderer.skybox;
|
||||
}
|
||||
{ // Rendering
|
||||
|
@ -121,12 +129,12 @@ int main(int, char *[]){
|
|||
auto pass = renderer->getPass();
|
||||
pass.start();
|
||||
|
||||
std::vector<std::pair<glm::mat4, Buffer *>> models;
|
||||
std::vector<std::pair<glm::mat4, Buffer *const>> models;
|
||||
std::optional<Frustum> furstum;
|
||||
if(options.culling) {
|
||||
world.getModels(models, options.voxel_size, camera.getFrustum());
|
||||
} else {
|
||||
world.getModels(models, options.voxel_size);
|
||||
furstum = {camera.getFrustum()};
|
||||
}
|
||||
world.getContouring()->getModels(models, camera.getFrustum(), options.voxel_size);
|
||||
reports.main.models_count = 0;
|
||||
reports.main.tris_count = 0;
|
||||
rmt_ScopedOpenGLSample(Render);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "pass/Program.hpp"
|
||||
#include "../contouring/Abstract.hpp"
|
||||
|
||||
void UI::setup(GLFWwindow* window) {
|
||||
// Setup Dear ImGui context
|
||||
|
@ -112,16 +113,14 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
/*if (show_debug_contouring) {
|
||||
ImGui::Begin("Debug: Contouring", &show_debug_contouring, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if(ImGui::Combo("Contouring", &contouring_idx, contouring::names)) {
|
||||
world.setContouring(contouring::getContouring(contouring_idx, &world));
|
||||
if (options.show_debug_contouring) {
|
||||
ImGui::Begin("Debug: Contouring", &options.show_debug_contouring, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if(ImGui::Combo("Contouring", &options.contouring_idx, /*contouring::names*/"\0")) {
|
||||
actions = actions | Actions::ChangeContouring;
|
||||
}
|
||||
if (ImGui::Button("Render all"))
|
||||
world.renderAll();
|
||||
world.getContouring()->onGui();
|
||||
state.contouring->onGui();
|
||||
ImGui::End();
|
||||
}*/
|
||||
}
|
||||
|
||||
if (options.show_debug_controls) {
|
||||
ImGui::Begin("Debug: Controls", &options.show_debug_controls, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace UI {
|
|||
RendererTextures = 1 << 4,
|
||||
World = 1 << 5,
|
||||
Camera = 1 << 6,
|
||||
ChangeContouring = 1 << 7,
|
||||
};
|
||||
inline Actions operator|(Actions a, Actions b) {
|
||||
return static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define CHUNK_LENGTH2 (CHUNK_LENGTH * CHUNK_LENGTH)
|
||||
#define CHUNK_SIZE (CHUNK_LENGTH2 * CHUNK_LENGTH)
|
||||
|
||||
class Buffer;
|
||||
/// World part as linear 3d voxel array
|
||||
struct Chunk {
|
||||
public:
|
||||
|
@ -51,8 +50,6 @@ public:
|
|||
}
|
||||
static std::optional<ushort> getNeighborIdx(ushort idx, Face dir);
|
||||
|
||||
Buffer *buffer = NULL;
|
||||
|
||||
private:
|
||||
/// Chunk data
|
||||
std::array<Voxel, CHUNK_SIZE> voxels;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include "World.hpp"
|
||||
|
||||
#include "../contouring/SurrondingFlatBox.hpp"
|
||||
#include "../render/buffer/ShortIndexedBuffer.hpp"
|
||||
#include "../contouring/Dummy.hpp"
|
||||
#include <Remotery.h>
|
||||
|
||||
World::World(const World::options& options) {
|
||||
World::World(const World::options &options): contouring(std::make_shared<contouring::Dummy>()) {
|
||||
setOptions(options);
|
||||
}
|
||||
World::~World() { }
|
||||
World::~World() {
|
||||
contouring = NULL;
|
||||
}
|
||||
|
||||
void World::update(const camera_pos& pos, World::report& rep) {
|
||||
const chunk_pos newPos = glm::divide(pos, chunk_voxel_pos(CHUNK_LENGTH));
|
||||
|
@ -19,44 +20,20 @@ void World::update(const camera_pos& pos, World::report& rep) {
|
|||
{
|
||||
rmt_ScopedCPUSample(Update, 0);
|
||||
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
|
||||
if (glm::length2(last_pos - chunkPos) > keepDistance * keepDistance
|
||||
&& unloadQueue.push(chunkPos)) {
|
||||
//TODO: unloadCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chunk->update()) { // MAYBE: update joints
|
||||
//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) {
|
||||
rmt_ScopedCPUSample(Render, 0);
|
||||
if (chunk->buffer != NULL)
|
||||
delete chunk->buffer;
|
||||
|
||||
std::vector<VertexData> vertices;
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (chunk->update()) { // MAYBE: also contour joints
|
||||
contouring->onUpdate(chunkPos, chunks); //TODO: get update update_type(simple(pos), complex)
|
||||
} else if (chunkChange) { //NOTE: must be solved before octrees
|
||||
contouring->onNotify(chunkPos, chunks);
|
||||
}
|
||||
}
|
||||
}
|
||||
contouring->update(pos);
|
||||
|
||||
rep.chunk_unload.push(unloadQueue.size());
|
||||
// Unload dead chunks
|
||||
|
@ -99,7 +76,8 @@ void World::update(const camera_pos& pos, World::report& rep) {
|
|||
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++) {
|
||||
//MAYBE: contouring dependant
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
const auto it = chunks.find(pos + g_face_offsets[i]);
|
||||
if (it != chunks.end())
|
||||
it->second->invalidate();
|
||||
|
@ -113,17 +91,7 @@ void World::setOptions(const World::options& options) {
|
|||
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});
|
||||
}
|
||||
}
|
||||
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});
|
||||
}
|
||||
void World::setContouring(std::shared_ptr<contouring::Abstract> ct) {
|
||||
contouring = ct;
|
||||
last_pos = chunk_pos(INT_MAX); // trigger chunkChange on next update
|
||||
}
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
#include <memory>
|
||||
#include "../data/unique_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "../data/geometry/Frustum.hpp"
|
||||
#include "Chunk.hpp"
|
||||
#define REPORT_BUFFER_SIZE 128
|
||||
|
||||
class Buffer;
|
||||
namespace contouring {
|
||||
class Abstract;
|
||||
};
|
||||
|
||||
class World {
|
||||
public:
|
||||
struct options {
|
||||
int loadDistance = 3;
|
||||
int keepDistance = 4;
|
||||
int loadDistance = 5;
|
||||
int keepDistance = 6;
|
||||
};
|
||||
struct report {
|
||||
circular_buffer<float> chunk_count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
|
@ -32,8 +34,13 @@ public:
|
|||
return {};
|
||||
return {it->second};
|
||||
}
|
||||
void getModels(std::vector<std::pair<glm::mat4, Buffer*>> &models, float scale) const;
|
||||
void getModels(std::vector<std::pair<glm::mat4, Buffer*>> &models, float scale, const Frustum& frustum) const;
|
||||
|
||||
/// Change contouring worker
|
||||
void setContouring(std::shared_ptr<contouring::Abstract>);
|
||||
/// Get current contouring worker
|
||||
std::shared_ptr<contouring::Abstract> getContouring() const {
|
||||
return contouring;
|
||||
}
|
||||
|
||||
private:
|
||||
chunk_pos last_pos = chunk_pos(INT_MAX);
|
||||
|
@ -41,9 +48,12 @@ private:
|
|||
Generator generator;
|
||||
std::unordered_map<chunk_pos, std::shared_ptr<Chunk>> chunks;
|
||||
|
||||
unique_queue<chunk_pos> loadQueue; // TODO: unique moving priority
|
||||
unique_queue<chunk_pos> loadQueue; // TODO: unique priority
|
||||
unique_queue<chunk_pos> unloadQueue;
|
||||
|
||||
int loadDistance;
|
||||
int keepDistance;
|
||||
|
||||
/// Contouring worker
|
||||
std::shared_ptr<contouring::Abstract> contouring;
|
||||
};
|
Loading…
Reference in New Issue