Doc and refactor
This commit is contained in:
parent
5a0c87cd7a
commit
978334c659
10
Doxyfile
10
Doxyfile
|
@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
|
|||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = Atomic
|
||||
PROJECT_NAME = Univerxel
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
|
@ -461,7 +461,7 @@ LOOKUP_CACHE_SIZE = 0
|
|||
# normally produced when WARNINGS is set to YES.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_ALL = NO
|
||||
|
||||
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
||||
# be included in the documentation.
|
||||
|
@ -823,7 +823,7 @@ WARN_LOGFILE =
|
|||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = /home/sheychen/Develop/Current/Atomic/src
|
||||
INPUT = ../src
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
@ -2354,7 +2354,7 @@ UML_LOOK = YES
|
|||
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
UML_LIMIT_NUM_FIELDS = 20
|
||||
|
||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||
# collaboration graphs will show the relations between templates and their
|
||||
|
@ -2362,7 +2362,7 @@ UML_LIMIT_NUM_FIELDS = 10
|
|||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
TEMPLATE_RELATIONS = YES
|
||||
TEMPLATE_RELATIONS = NO
|
||||
|
||||
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
|
||||
# YES then doxygen will generate a graph for each documented file showing the
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Univerxel <!-- omit in toc -->
|
||||
|
||||
Work in progress galaxy down to atom (mostly centimeter) Voxel game
|
||||
Work in progress galaxy down to atom (mostly centimeter) voxel game
|
||||
|
||||
## Table of Contents <!-- omit in toc -->
|
||||
|
||||
|
@ -90,7 +90,7 @@ See [Features](TODO.md)
|
|||
<!-- LICENSE -->
|
||||
## License
|
||||
|
||||
Distributed under the MIT License. See (LICENSE)[LICENSE] for more information.
|
||||
Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
|
||||
|
||||
|
||||
|
||||
|
@ -99,4 +99,4 @@ Distributed under the MIT License. See (LICENSE)[LICENSE] for more information.
|
|||
|
||||
Maelys Bois - [/me](https://git.wadza.fr/me) - me@wadza.fr
|
||||
|
||||
Project Link: [https://git.wadza.fr/me/atomic](https://git.wadza.fr/me/atomic)
|
||||
Project Link: [https://git.wadza.fr/me/univerxel](https://git.wadza.fr/me/univerxel)
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "../data/glm.hpp"
|
||||
#include "../render/buffer/Buffer.hpp"
|
||||
#include "../render/buffer/Abstract.hpp"
|
||||
#include "../data/geometry/Frustum.hpp"
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
#include <memory>
|
||||
#include <toml.h>
|
||||
#include <robin_hood.h>
|
||||
|
||||
class World;
|
||||
class Chunk;
|
||||
namespace world {
|
||||
class Chunk;
|
||||
}
|
||||
/// Mesh creation
|
||||
namespace contouring {
|
||||
/// Generating mesh from world data
|
||||
class Abstract {
|
||||
|
@ -22,10 +24,10 @@ namespace contouring {
|
|||
virtual void update(const camera_pos &pos) = 0;
|
||||
|
||||
/// Chunk data change
|
||||
virtual void onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>>& data, Faces neighbors) = 0;
|
||||
virtual void onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>>& data, geometry::Faces neighbors) = 0;
|
||||
/// Chunk existante ping
|
||||
/// @note notify for chunks entering view while moving
|
||||
virtual void onNotify(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) = 0;
|
||||
virtual void onNotify(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data) = 0;
|
||||
/// Display ImGui config
|
||||
virtual void onGui() = 0;
|
||||
/// Get options
|
||||
|
@ -33,6 +35,6 @@ namespace contouring {
|
|||
|
||||
/// 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;
|
||||
virtual void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &buffers, const std::optional<geometry::Frustum>& frustum, float scale) = 0;
|
||||
};
|
||||
}
|
|
@ -38,10 +38,10 @@ namespace contouring {
|
|||
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) {
|
||||
void AbstractFlat::getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &out, const std::optional<geometry::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)))))
|
||||
if (buffer != NULL && (!frustum.has_value() || frustum.value().contains(geometry::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});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include "Abstract.hpp"
|
||||
|
||||
class World;
|
||||
class Chunk;
|
||||
namespace contouring {
|
||||
/// Generating mesh for chunks 1:1
|
||||
class AbstractFlat: public Abstract {
|
||||
|
@ -21,7 +19,7 @@ namespace contouring {
|
|||
|
||||
/// 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;
|
||||
void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &out, const std::optional<geometry::Frustum> &frustum, float scale) override;
|
||||
|
||||
protected:
|
||||
bool inline inLoadRange(const chunk_pos& point) const {
|
||||
|
@ -31,7 +29,7 @@ namespace contouring {
|
|||
return glm::length2(center - point) <= keepDistance * keepDistance;
|
||||
}
|
||||
|
||||
robin_hood::unordered_map<chunk_pos, Buffer *> buffers;
|
||||
robin_hood::unordered_map<chunk_pos, buffer::Abstract *> buffers;
|
||||
chunk_pos center = chunk_pos(INT_MAX);
|
||||
|
||||
int loadDistance = 3;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include "Abstract.hpp"
|
||||
|
||||
class World;
|
||||
class Chunk;
|
||||
namespace contouring {
|
||||
/// Useless contouring
|
||||
class Dummy: public Abstract {
|
||||
|
@ -12,10 +10,10 @@ namespace contouring {
|
|||
virtual ~Dummy() { }
|
||||
|
||||
void update(const camera_pos &) override { }
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &, Faces) override {}
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override { }
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &, geometry::Faces) override {}
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &) override { }
|
||||
void onGui() override { }
|
||||
std::string getOptions() override { return ""; }
|
||||
void getModels(std::vector<std::pair<glm::mat4, Buffer *const>> &, const std::optional<Frustum>&, float) override { }
|
||||
void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &, const std::optional<geometry::Frustum>&, float) override { }
|
||||
};
|
||||
}
|
|
@ -19,7 +19,7 @@ namespace contouring {
|
|||
loadQueue.wait();
|
||||
if (loadQueue.pop(ctx)) {
|
||||
rmt_ScopedCPUSample(ProcessContouring, 0);
|
||||
ShortIndexedBuffer::Data data;
|
||||
buffer::ShortIndexed::Data data;
|
||||
render(ctx.second, data);
|
||||
loadedQueue.push({ctx.first, data});
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace contouring {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
void FlatDualMC::enqueue(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
void FlatDualMC::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) {
|
||||
|
@ -59,16 +59,16 @@ namespace contouring {
|
|||
}
|
||||
}
|
||||
|
||||
void FlatDualMC::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data, Faces neighbors) {
|
||||
void FlatDualMC::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data, geometry::Faces neighbors) {
|
||||
enqueue(pos, data);
|
||||
if (neighbors && (Faces::Left | Faces::Down | Faces::Backward)) {
|
||||
if (neighbors && (geometry::Faces::Left | geometry::Faces::Down | geometry::Faces::Backward)) {
|
||||
for (size_t i = 1; i < 8; i++) {
|
||||
enqueue(pos - surrounding::g_corner_offsets[i], data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlatDualMC::onNotify(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
void FlatDualMC::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);
|
||||
}
|
||||
|
@ -76,12 +76,12 @@ namespace contouring {
|
|||
|
||||
void FlatDualMC::update(const camera_pos& pos) {
|
||||
AbstractFlat::update(pos);
|
||||
std::pair<chunk_pos, ShortIndexedBuffer::Data> out;
|
||||
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 ShortIndexedBuffer(GL_TRIANGLES, out.second);
|
||||
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)
|
||||
|
@ -106,7 +106,7 @@ namespace contouring {
|
|||
ImGui::Checkbox("Manifold", &manifold);
|
||||
}
|
||||
|
||||
void FlatDualMC::render(const surrounding::corners &surrounding, ShortIndexedBuffer::Data &out) const {
|
||||
void FlatDualMC::render(const surrounding::corners &surrounding, buffer::ShortIndexed::Data &out) const {
|
||||
const int SIZE = CHUNK_LENGTH + 3;
|
||||
std::vector<dualmc::DualMC<float>::Point> grid;
|
||||
grid.reserve(SIZE * SIZE * SIZE);
|
||||
|
@ -116,7 +116,7 @@ namespace contouring {
|
|||
for (int x = 0; x < SIZE; x++) {
|
||||
const auto chunk = surrounding[(z >= CHUNK_LENGTH) + (y >= CHUNK_LENGTH)*2 + (x >= CHUNK_LENGTH)*4];
|
||||
// MAYBE: area copy
|
||||
const auto voxel = chunk->get(Chunk::getIdx(x % CHUNK_LENGTH, y % CHUNK_LENGTH, z % CHUNK_LENGTH));
|
||||
const auto voxel = chunk->getAt(chunk_voxel_pos(x % CHUNK_LENGTH, y % CHUNK_LENGTH, z % CHUNK_LENGTH));
|
||||
grid.push_back({voxel.Density * 1.f / UCHAR_MAX, voxel.Material});
|
||||
}}}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ namespace contouring {
|
|||
std::vector<dualmc::Tri> dmc_tris;
|
||||
|
||||
dualmc::DualMC<float> builder;
|
||||
builder.buildTris(&grid.front(), SIZE, SIZE, SIZE, iso, materials::roughness.cbegin(), manifold, dmc_vertices, dmc_tris);
|
||||
builder.buildTris(&grid.front(), SIZE, SIZE, SIZE, iso, world::materials::roughness.cbegin(), manifold, dmc_vertices, dmc_tris);
|
||||
|
||||
out.vertices.reserve(dmc_vertices.size());
|
||||
out.materials.reserve(dmc_vertices.size());
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "../render/buffer/ShortIndexedBuffer.hpp"
|
||||
#include "../render/buffer/ShortIndexed.hpp"
|
||||
#include <thread>
|
||||
|
||||
#define REPORT_BUFFER_SIZE 128
|
||||
|
||||
using namespace data;
|
||||
namespace contouring {
|
||||
/// Dual Marching Cube 1:1 contouring
|
||||
class FlatDualMC: public AbstractFlat {
|
||||
public:
|
||||
FlatDualMC(const std::string&);
|
||||
|
@ -24,14 +26,14 @@ namespace contouring {
|
|||
std::string getOptions() override;
|
||||
|
||||
/// Chunk data change
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &, Faces) override;
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &, geometry::Faces) override;
|
||||
/// Chunk existante ping
|
||||
/// @note notify for chunks entering view while moving
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override;
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &) override;
|
||||
|
||||
protected:
|
||||
safe_priority_queue_map<chunk_pos, surrounding::corners, int> loadQueue;
|
||||
safe_queue<std::pair<chunk_pos, ShortIndexedBuffer::Data>> loadedQueue;
|
||||
safe_queue<std::pair<chunk_pos, buffer::ShortIndexed::Data>> loadedQueue;
|
||||
|
||||
struct report {
|
||||
circular_buffer<float> count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
|
@ -42,11 +44,11 @@ namespace contouring {
|
|||
bool running = true;
|
||||
std::vector<std::thread> workers;
|
||||
|
||||
void enqueue(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &);
|
||||
void enqueue(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &);
|
||||
|
||||
float iso = .1f;
|
||||
bool manifold = true;
|
||||
|
||||
void render(const surrounding::corners &surrounding, ShortIndexedBuffer::Data& out) const;
|
||||
void render(const surrounding::corners &surrounding, buffer::ShortIndexed::Data& out) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#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++) {
|
||||
|
@ -14,11 +15,11 @@ namespace contouring {
|
|||
loadQueue.wait();
|
||||
if (loadQueue.pop(ctx)) {
|
||||
rmt_ScopedCPUSample(ProcessContouring, 0);
|
||||
std::vector<VertexData> vertices;
|
||||
std::vector<buffer::VertexData> vertices;
|
||||
render(ctx.second, vertices);
|
||||
{
|
||||
rmt_ScopedCPUSample(Index, 0);
|
||||
loadedQueue.push({ctx.first, ShortIndexedBuffer::Data(vertices)});
|
||||
loadedQueue.push({ctx.first, buffer::ShortIndexed::Data(vertices)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +36,7 @@ namespace contouring {
|
|||
}
|
||||
}
|
||||
|
||||
void FlatSurroundingBox::enqueue(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
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) {
|
||||
|
@ -46,7 +47,7 @@ namespace contouring {
|
|||
}
|
||||
}
|
||||
|
||||
void FlatSurroundingBox::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data, Faces neighbors) {
|
||||
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);
|
||||
|
@ -67,7 +68,7 @@ namespace contouring {
|
|||
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<Chunk>> &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);
|
||||
}
|
||||
|
@ -75,12 +76,12 @@ namespace contouring {
|
|||
|
||||
void FlatSurroundingBox::update(const camera_pos& pos) {
|
||||
AbstractFlat::update(pos);
|
||||
std::pair<chunk_pos, ShortIndexedBuffer::Data> out;
|
||||
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 ShortIndexedBuffer(GL_TRIANGLES, out.second);
|
||||
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)
|
||||
|
@ -103,22 +104,22 @@ namespace contouring {
|
|||
}
|
||||
|
||||
bool FlatSurroundingBox::isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx) {
|
||||
return surrounding[idx.first]->begin()[idx.second].Density < UCHAR_MAX; // MAYBE: materials::transparent
|
||||
return surrounding[idx.first]->get(idx.second).Density < UCHAR_MAX; // MAYBE: materials::transparent
|
||||
}
|
||||
|
||||
void FlatSurroundingBox::render(const surrounding::faces &surrounding, std::vector<VertexData> &vertices) {
|
||||
const auto voxels = surrounding[surrounding::CENTER]->begin();
|
||||
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 (voxels[i].Density > 0) {
|
||||
Faces faces = voxels[i].Density < UCHAR_MAX ? Faces::All :
|
||||
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, Chunk::getPosition(i), voxels[i].Material, faces, glm::vec3(voxels[i].Density * 1.f / UCHAR_MAX));
|
||||
box::addCube(vertices, world::Chunk::getPosition(i), center->get(i).Material, faces, glm::vec3(center->get(i).Density * 1.f / UCHAR_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "../render/buffer/ShortIndexedBuffer.hpp"
|
||||
#include "../render/buffer/ShortIndexed.hpp"
|
||||
#include <thread>
|
||||
|
||||
#define REPORT_BUFFER_SIZE 128
|
||||
|
||||
using namespace data;
|
||||
namespace contouring {
|
||||
/// Stupid cubes 1:1 contouring
|
||||
class FlatSurroundingBox: public AbstractFlat {
|
||||
public:
|
||||
FlatSurroundingBox(const std::string&);
|
||||
|
@ -22,14 +24,14 @@ namespace contouring {
|
|||
void onGui() override;
|
||||
|
||||
/// Chunk data change
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &, Faces) override;
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &, geometry::Faces) override;
|
||||
/// Chunk existante ping
|
||||
/// @note notify for chunks entering view while moving
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override;
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &) override;
|
||||
|
||||
protected:
|
||||
safe_priority_queue_map<chunk_pos, surrounding::faces, int> loadQueue;
|
||||
safe_queue<std::pair<chunk_pos, ShortIndexedBuffer::Data>> loadedQueue;
|
||||
safe_queue<std::pair<chunk_pos, buffer::ShortIndexed::Data>> loadedQueue;
|
||||
|
||||
struct report {
|
||||
circular_buffer<float> count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
|
@ -40,10 +42,10 @@ namespace contouring {
|
|||
bool running = true;
|
||||
std::vector<std::thread> workers;
|
||||
|
||||
void enqueue(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &);
|
||||
void enqueue(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &);
|
||||
|
||||
private:
|
||||
static inline bool isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx);
|
||||
static void render(const surrounding::faces &surrounding, std::vector<VertexData> &vertices);
|
||||
static void render(const surrounding::faces &surrounding, std::vector<buffer::VertexData> &vertices);
|
||||
};
|
||||
}
|
||||
} // namespace contouring
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../data/geometry/Faces.hpp"
|
||||
#include "../render/buffer/VertexData.hpp"
|
||||
|
||||
using namespace geometry;
|
||||
namespace contouring::box {
|
||||
static const auto BOX_FACES = 6;
|
||||
|
||||
|
@ -24,13 +25,13 @@ namespace contouring::box {
|
|||
glm::rotate<float>(glm::mat4(1), glm::half_pi<float>(), glm::vec3(0, 1, 0)),
|
||||
};
|
||||
|
||||
static void addQuad(std::vector<VertexData> & out, glm::vec3 position, ushort material, Face face, glm::vec3 size) {
|
||||
static void addQuad(std::vector<buffer::VertexData> & out, glm::vec3 position, ushort material, Face face, glm::vec3 size) {
|
||||
for (auto vertex : g_quad_vertices) {
|
||||
out.push_back(VertexData{glm::vec3(g_cube_rotate[static_cast<int>(face)] * glm::vec4(vertex, 1)) * size + position, material, g_cube_normals[static_cast<int>(face)]});
|
||||
out.push_back(buffer::VertexData{glm::vec3(g_cube_rotate[static_cast<int>(face)] * glm::vec4(vertex, 1)) * size + position, material, g_cube_normals[static_cast<int>(face)]});
|
||||
}
|
||||
}
|
||||
|
||||
static void addCube(std::vector<VertexData>& out, glm::vec3 position, uint material, Faces faces = Faces::All, glm::vec3 size = glm::vec3(1)) {
|
||||
static void addCube(std::vector<buffer::VertexData>& out, glm::vec3 position, uint material, Faces faces = Faces::All, glm::vec3 size = glm::vec3(1)) {
|
||||
if (faces && Faces::Right)
|
||||
addQuad(out, position, material, Face::Right, size);
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
#include "../world/Chunk.hpp"
|
||||
|
||||
using namespace geometry;
|
||||
namespace contouring::surrounding {
|
||||
bool load(faces &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks) {
|
||||
bool load(faces &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &chunks) {
|
||||
{
|
||||
const auto it = chunks.find(chunkPos);
|
||||
if (it == chunks.end())
|
||||
|
@ -58,7 +59,7 @@ namespace contouring::surrounding {
|
|||
}
|
||||
}
|
||||
|
||||
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks) {
|
||||
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &chunks) {
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
const auto it = chunks.find(chunkPos + g_corner_offsets[i]);
|
||||
if (it == chunks.end())
|
||||
|
|
|
@ -4,16 +4,18 @@
|
|||
#include <memory>
|
||||
#include <robin_hood.h>
|
||||
|
||||
class Chunk;
|
||||
namespace world {
|
||||
class Chunk;
|
||||
}
|
||||
namespace contouring::surrounding {
|
||||
const auto CENTER = 6;
|
||||
typedef std::array<std::shared_ptr<const Chunk>, CENTER+1> faces;
|
||||
typedef std::array<std::shared_ptr<const world::Chunk>, CENTER+1> faces;
|
||||
|
||||
bool load(faces &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks);
|
||||
bool load(faces &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &chunks);
|
||||
|
||||
std::pair<ushort, ushort> getNeighborIdx(ushort idx, Face face);
|
||||
std::pair<ushort, ushort> getNeighborIdx(ushort idx, geometry::Face face);
|
||||
|
||||
typedef std::array<std::shared_ptr<const Chunk>, 8> corners;
|
||||
typedef std::array<std::shared_ptr<const world::Chunk>, 8> corners;
|
||||
const glm::ivec3 g_corner_offsets[8] = {
|
||||
glm::ivec3(0, 0, 0),
|
||||
glm::ivec3(0, 0, 1),
|
||||
|
@ -25,5 +27,5 @@ namespace contouring::surrounding {
|
|||
glm::ivec3(1, 1, 1),
|
||||
};
|
||||
|
||||
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks);
|
||||
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &chunks);
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
}
|
||||
|
||||
glm::vec3 getDirection() const { return glm::vec3(cos(VerticalAngle) * sin(HorizontalAngle), sin(VerticalAngle), cos(VerticalAngle) * cos(HorizontalAngle)); }
|
||||
inline Frustum getFrustum() const { return Frustum(ViewMatrix, ProjectionMatrix); }
|
||||
inline Ray getRay() const { return Ray(Position, getDirection(), o.far); }
|
||||
inline geometry::Frustum getFrustum() const { return geometry::Frustum(ViewMatrix, ProjectionMatrix); }
|
||||
inline geometry::Ray getRay() const { return geometry::Ray(Position, getDirection(), o.far); }
|
||||
|
||||
glm::mat4 getViewMatrix() const { return ViewMatrix; }
|
||||
glm::mat4 getProjectionMatrix() const { return ProjectionMatrix; }
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
/// Looping array
|
||||
template <class T>
|
||||
struct circular_buffer {
|
||||
circular_buffer(size_t size): size(size), buffer(std::unique_ptr<T[]>(new T[size])) { }
|
||||
circular_buffer(size_t size, const T& zero): circular_buffer(size) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
buffer[i] = zero;
|
||||
/// Generic containers
|
||||
namespace data {
|
||||
/// Looping array
|
||||
template <class T>
|
||||
struct circular_buffer {
|
||||
circular_buffer(size_t size): size(size), buffer(std::unique_ptr<T[]>(new T[size])) { }
|
||||
circular_buffer(size_t size, const T& zero): circular_buffer(size) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
buffer[i] = zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t last = 0;
|
||||
size_t size;
|
||||
std::unique_ptr<T[]> buffer;
|
||||
size_t last = 0;
|
||||
size_t size;
|
||||
std::unique_ptr<T[]> buffer;
|
||||
|
||||
void push(T in) {
|
||||
last = (last + 1) % size;
|
||||
buffer[last] = in;
|
||||
}
|
||||
T current() const {
|
||||
return buffer[last];
|
||||
}
|
||||
};
|
||||
void push(T in) {
|
||||
last = (last + 1) % size;
|
||||
buffer[last] = in;
|
||||
}
|
||||
T current() const {
|
||||
return buffer[last];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,40 +3,42 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <iostream>
|
||||
|
||||
/// Axis Aligned Floating Box
|
||||
struct Box {
|
||||
enum class ContainmentType {
|
||||
Disjoint = false, Intersects, Contains
|
||||
namespace geometry {
|
||||
/// Axis Aligned Floating Box
|
||||
struct Box {
|
||||
enum class ContainmentType {
|
||||
Disjoint = false, Intersects, Contains
|
||||
};
|
||||
|
||||
Box(glm::vec3 min, glm::vec3 max): Min(min), Max(max) {
|
||||
assert(("Min > Max", max.x >= min.x && max.y >= min.y && max.z >= min.z));
|
||||
}
|
||||
inline static Box fromCenter(glm::vec3 center, float radius) { return Box(center - radius, center + radius); }
|
||||
inline static Box fromMin(glm::vec3 min, glm::vec3 size) { return Box(min, min + size); }
|
||||
|
||||
glm::vec3 Min;
|
||||
glm::vec3 Max;
|
||||
|
||||
ContainmentType contains(const Box& box) const {
|
||||
//test if all corner is in the same side of a face by just checking min and max
|
||||
if (box.Max.x < Min.x
|
||||
|| box.Min.x > Max.x
|
||||
|| box.Max.y < Min.y
|
||||
|| box.Min.y > Max.y
|
||||
|| box.Max.z < Min.z
|
||||
|| box.Min.z > Max.z)
|
||||
return ContainmentType::Disjoint;
|
||||
|
||||
|
||||
if (box.Min.x >= Min.x
|
||||
&& box.Max.x <= Max.x
|
||||
&& box.Min.y >= Min.y
|
||||
&& box.Max.y <= Max.y
|
||||
&& box.Min.z >= Min.z
|
||||
&& box.Max.z <= Max.z)
|
||||
return ContainmentType::Contains;
|
||||
|
||||
return ContainmentType::Intersects;
|
||||
}
|
||||
};
|
||||
|
||||
Box(glm::vec3 min, glm::vec3 max): Min(min), Max(max) {
|
||||
assert(("Min > Max", max.x >= min.x && max.y >= min.y && max.z >= min.z));
|
||||
}
|
||||
inline static Box fromCenter(glm::vec3 center, float radius) { return Box(center - radius, center + radius); }
|
||||
inline static Box fromMin(glm::vec3 min, glm::vec3 size) { return Box(min, min + size); }
|
||||
|
||||
glm::vec3 Min;
|
||||
glm::vec3 Max;
|
||||
|
||||
ContainmentType contains(const Box& box) const {
|
||||
//test if all corner is in the same side of a face by just checking min and max
|
||||
if (box.Max.x < Min.x
|
||||
|| box.Min.x > Max.x
|
||||
|| box.Max.y < Min.y
|
||||
|| box.Min.y > Max.y
|
||||
|| box.Max.z < Min.z
|
||||
|| box.Min.z > Max.z)
|
||||
return ContainmentType::Disjoint;
|
||||
|
||||
|
||||
if (box.Min.x >= Min.x
|
||||
&& box.Max.x <= Max.x
|
||||
&& box.Min.y >= Min.y
|
||||
&& box.Max.y <= Max.y
|
||||
&& box.Min.z >= Min.z
|
||||
&& box.Max.z <= Max.z)
|
||||
return ContainmentType::Contains;
|
||||
|
||||
return ContainmentType::Intersects;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -2,34 +2,37 @@
|
|||
|
||||
#include "../glm.hpp"
|
||||
|
||||
enum class Face {
|
||||
Right, Left, Up, Down, Forward, Backward
|
||||
};
|
||||
const glm::ivec3 g_face_offsets[6] = {
|
||||
glm::ivec3(1,0,0), glm::ivec3(-1,0,0),
|
||||
glm::ivec3(0,1,0), glm::ivec3(0,-1,0),
|
||||
glm::ivec3(0,0,1), glm::ivec3(0,0,-1),
|
||||
};
|
||||
/// Math utils
|
||||
namespace geometry {
|
||||
enum class Face {
|
||||
Right, Left, Up, Down, Forward, Backward
|
||||
};
|
||||
const glm::ivec3 g_face_offsets[6] = {
|
||||
glm::ivec3(1,0,0), glm::ivec3(-1,0,0),
|
||||
glm::ivec3(0,1,0), glm::ivec3(0,-1,0),
|
||||
glm::ivec3(0,0,1), glm::ivec3(0,0,-1),
|
||||
};
|
||||
|
||||
enum class Faces {
|
||||
None = 0,
|
||||
Right = 1,
|
||||
Left = 2,
|
||||
Up = 4,
|
||||
Down = 8,
|
||||
Forward = 16,
|
||||
Backward = 32,
|
||||
All = 63
|
||||
};
|
||||
inline Faces operator|(Faces a, Faces b) {
|
||||
return static_cast<Faces>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
inline Faces operator&(Faces a, Faces b) {
|
||||
return static_cast<Faces>(static_cast<int>(a) & static_cast<int>(b));
|
||||
}
|
||||
inline Faces operator&(bool a, Faces b) {
|
||||
return (a ? Faces::All : Faces::None) & b;
|
||||
}
|
||||
inline bool operator&&(Faces a, Faces b) {
|
||||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
enum class Faces {
|
||||
None = 0,
|
||||
Right = 1,
|
||||
Left = 2,
|
||||
Up = 4,
|
||||
Down = 8,
|
||||
Forward = 16,
|
||||
Backward = 32,
|
||||
All = 63
|
||||
};
|
||||
inline Faces operator|(Faces a, Faces b) {
|
||||
return static_cast<Faces>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
inline Faces operator&(Faces a, Faces b) {
|
||||
return static_cast<Faces>(static_cast<int>(a) & static_cast<int>(b));
|
||||
}
|
||||
inline Faces operator&(bool a, Faces b) {
|
||||
return (a ? Faces::All : Faces::None) & b;
|
||||
}
|
||||
inline bool operator&&(Faces a, Faces b) {
|
||||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,82 +2,84 @@
|
|||
|
||||
#include "Box.hpp"
|
||||
|
||||
/// Bounding frustum
|
||||
struct Frustum {
|
||||
glm::vec4 planes[6];
|
||||
namespace geometry {
|
||||
/// Bounding frustum
|
||||
struct Frustum {
|
||||
glm::vec4 planes[6];
|
||||
|
||||
enum FrustumSide
|
||||
{
|
||||
RIGHT = 0, // The RIGHT side of the frustum
|
||||
LEFT = 1, // The LEFT side of the frustum
|
||||
BOTTOM = 2, // The BOTTOM side of the frustum
|
||||
TOP = 3, // The TOP side of the frustum
|
||||
BACK = 4, // The BACK side of the frustum
|
||||
FRONT = 5 // The FRONT side of the frustum
|
||||
};
|
||||
enum FrustumSide
|
||||
{
|
||||
RIGHT = 0, // The RIGHT side of the frustum
|
||||
LEFT = 1, // The LEFT side of the frustum
|
||||
BOTTOM = 2, // The BOTTOM side of the frustum
|
||||
TOP = 3, // The TOP side of the frustum
|
||||
BACK = 4, // The BACK side of the frustum
|
||||
FRONT = 5 // The FRONT side of the frustum
|
||||
};
|
||||
|
||||
void normalize(glm::vec4 &plane) {
|
||||
plane /= (float)sqrt(plane.x * plane.x + plane.y * plane.y + plane.z * plane.z);
|
||||
}
|
||||
|
||||
Frustum(const glm::mat4& view_matrix, const glm::mat4& proj_matrix) {
|
||||
const float *proj = &proj_matrix[0][0];
|
||||
const float *modl = &view_matrix[0][0];
|
||||
float clip[16]; //clipping planes
|
||||
|
||||
clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12];
|
||||
clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13];
|
||||
clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14];
|
||||
clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15];
|
||||
|
||||
clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12];
|
||||
clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13];
|
||||
clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14];
|
||||
clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15];
|
||||
|
||||
clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12];
|
||||
clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13];
|
||||
clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14];
|
||||
clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15];
|
||||
|
||||
clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12];
|
||||
clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13];
|
||||
clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14];
|
||||
clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15];
|
||||
|
||||
planes[RIGHT] = glm::vec4(clip[3] - clip[0], clip[7] - clip[4], clip[11] - clip[8], clip[15] - clip[12]);
|
||||
normalize(planes[RIGHT]);
|
||||
|
||||
planes[LEFT] = glm::vec4(clip[3] + clip[0], clip[7] + clip[4], clip[11] + clip[8], clip[15] + clip[12]);
|
||||
normalize(planes[LEFT]);
|
||||
|
||||
planes[BOTTOM] = glm::vec4(clip[3] + clip[1], clip[7] + clip[5], clip[11] + clip[9], clip[15] + clip[13]);
|
||||
normalize(planes[BOTTOM]);
|
||||
|
||||
planes[TOP] = glm::vec4(clip[3] - clip[1], clip[7] - clip[5], clip[11] - clip[9], clip[15] - clip[13]);
|
||||
normalize(planes[TOP]);
|
||||
|
||||
planes[BACK] = glm::vec4(clip[3] - clip[2], clip[7] - clip[6], clip[11] - clip[10], clip[15] - clip[14]);
|
||||
normalize(planes[BACK]);
|
||||
|
||||
planes[FRONT] = glm::vec4(clip[3] + clip[2], clip[7] + clip[6], clip[11] + clip[10], clip[15] + clip[14]);
|
||||
normalize(planes[FRONT]);
|
||||
}
|
||||
|
||||
/// Check if box is contained
|
||||
inline bool contains(const Box &box) const {
|
||||
bool inside = true;
|
||||
//test all 6 frustum planes
|
||||
for (int i = 0; i<6; i++) {
|
||||
//pick closest point to plane and check if it behind the plane
|
||||
//if yes - object outside frustum
|
||||
float d = std::max(box.Min.x * planes[i].x, box.Max.x * planes[i].x)
|
||||
+ std::max(box.Min.y * planes[i].y, box.Max.y * planes[i].y)
|
||||
+ std::max(box.Min.z * planes[i].z, box.Max.z * planes[i].z)
|
||||
+ planes[i].w;
|
||||
inside &= d > 0;
|
||||
//return false; //with flag works faster
|
||||
void normalize(glm::vec4 &plane) {
|
||||
plane /= (float)sqrt(plane.x * plane.x + plane.y * plane.y + plane.z * plane.z);
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
};
|
||||
|
||||
Frustum(const glm::mat4& view_matrix, const glm::mat4& proj_matrix) {
|
||||
const float *proj = &proj_matrix[0][0];
|
||||
const float *modl = &view_matrix[0][0];
|
||||
float clip[16]; //clipping planes
|
||||
|
||||
clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] + modl[3] * proj[12];
|
||||
clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] + modl[3] * proj[13];
|
||||
clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] + modl[3] * proj[14];
|
||||
clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] + modl[3] * proj[15];
|
||||
|
||||
clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] + modl[7] * proj[12];
|
||||
clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] + modl[7] * proj[13];
|
||||
clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] + modl[7] * proj[14];
|
||||
clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] + modl[7] * proj[15];
|
||||
|
||||
clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] + modl[11] * proj[12];
|
||||
clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] + modl[11] * proj[13];
|
||||
clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] + modl[11] * proj[14];
|
||||
clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] + modl[11] * proj[15];
|
||||
|
||||
clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] + modl[15] * proj[12];
|
||||
clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] + modl[15] * proj[13];
|
||||
clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] + modl[15] * proj[14];
|
||||
clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] + modl[15] * proj[15];
|
||||
|
||||
planes[RIGHT] = glm::vec4(clip[3] - clip[0], clip[7] - clip[4], clip[11] - clip[8], clip[15] - clip[12]);
|
||||
normalize(planes[RIGHT]);
|
||||
|
||||
planes[LEFT] = glm::vec4(clip[3] + clip[0], clip[7] + clip[4], clip[11] + clip[8], clip[15] + clip[12]);
|
||||
normalize(planes[LEFT]);
|
||||
|
||||
planes[BOTTOM] = glm::vec4(clip[3] + clip[1], clip[7] + clip[5], clip[11] + clip[9], clip[15] + clip[13]);
|
||||
normalize(planes[BOTTOM]);
|
||||
|
||||
planes[TOP] = glm::vec4(clip[3] - clip[1], clip[7] - clip[5], clip[11] - clip[9], clip[15] - clip[13]);
|
||||
normalize(planes[TOP]);
|
||||
|
||||
planes[BACK] = glm::vec4(clip[3] - clip[2], clip[7] - clip[6], clip[11] - clip[10], clip[15] - clip[14]);
|
||||
normalize(planes[BACK]);
|
||||
|
||||
planes[FRONT] = glm::vec4(clip[3] + clip[2], clip[7] + clip[6], clip[11] + clip[10], clip[15] + clip[14]);
|
||||
normalize(planes[FRONT]);
|
||||
}
|
||||
|
||||
/// Check if box is contained
|
||||
inline bool contains(const Box &box) const {
|
||||
bool inside = true;
|
||||
//test all 6 frustum planes
|
||||
for (int i = 0; i<6; i++) {
|
||||
//pick closest point to plane and check if it behind the plane
|
||||
//if yes - object outside frustum
|
||||
float d = std::max(box.Min.x * planes[i].x, box.Max.x * planes[i].x)
|
||||
+ std::max(box.Min.y * planes[i].y, box.Max.y * planes[i].y)
|
||||
+ std::max(box.Min.z * planes[i].z, box.Max.z * planes[i].z)
|
||||
+ planes[i].w;
|
||||
inside &= d > 0;
|
||||
//return false; //with flag works faster
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,83 +3,85 @@
|
|||
#include "Box.hpp"
|
||||
#include "../glm.hpp"
|
||||
|
||||
/// Raycast with distance
|
||||
struct Ray {
|
||||
glm::vec3 from;
|
||||
glm::vec3 dir;
|
||||
float dist;
|
||||
namespace geometry {
|
||||
/// Raycast with distance
|
||||
struct Ray {
|
||||
glm::vec3 from;
|
||||
glm::vec3 dir;
|
||||
float dist;
|
||||
|
||||
// MAYBE: Ray(const glm::mat4& view_matrix) { }
|
||||
Ray(const glm::vec3& from, const glm::vec3& dir, float dist): from(from), dir(glm::normalize(dir)), dist(dist) { }
|
||||
// MAYBE: Ray(const glm::mat4& view_matrix) { }
|
||||
Ray(const glm::vec3& from, const glm::vec3& dir, float dist): from(from), dir(glm::normalize(dir)), dist(dist) { }
|
||||
|
||||
inline Ray operator/(float scale) const noexcept {
|
||||
return Ray(from / scale, dir, dist / scale);
|
||||
}
|
||||
|
||||
/// Get path points in integer grid
|
||||
/// @note not precise enough
|
||||
inline void grid(std::vector<voxel_pos>& points) const {
|
||||
voxel_pos current = from + glm::vec3(.5f);
|
||||
voxel_pos d = dir * dist;
|
||||
voxel_pos inc = voxel_pos((d.x < 0) ? -1 : 1, (d.y < 0) ? -1 : 1, (d.z < 0) ? -1 : 1);
|
||||
voxel_pos size = glm::abs(d);
|
||||
voxel_pos delta = size << 1ll;
|
||||
|
||||
if ((size.x >= size.y) && (size.x >= size.z)) {
|
||||
int err_1 = delta.y - size.x;
|
||||
int err_2 = delta.z - size.x;
|
||||
points.reserve(size.x + 1);
|
||||
for (int i = 0; i < size.x; i++) {
|
||||
points.push_back(current);
|
||||
if (err_1 > 0) {
|
||||
current.y += inc.y;
|
||||
err_1 -= delta.x;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
current.z += inc.z;
|
||||
err_2 -= delta.x;
|
||||
}
|
||||
err_1 += delta.y;
|
||||
err_2 += delta.z;
|
||||
current.x += inc.x;
|
||||
}
|
||||
} else if ((size.y >= size.x) && (size.y >= size.z)) {
|
||||
int err_1 = delta.x - size.y;
|
||||
int err_2 = delta.z - size.y;
|
||||
points.reserve(size.y + 1);
|
||||
for (int i = 0; i < size.y; i++) {
|
||||
points.push_back(current);
|
||||
if (err_1 > 0) {
|
||||
current.x += inc.x;
|
||||
err_1 -= delta.y;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
current.z += inc.z;
|
||||
err_2 -= delta.y;
|
||||
}
|
||||
err_1 += delta.x;
|
||||
err_2 += delta.z;
|
||||
current.y += inc.y;
|
||||
}
|
||||
} else {
|
||||
int err_1 = delta.y - size.z;
|
||||
int err_2 = delta.x - size.z;
|
||||
points.reserve(size.z + 1);
|
||||
for (int i = 0; i < size.z; i++) {
|
||||
points.push_back(current);
|
||||
if (err_1 > 0) {
|
||||
current.y += inc.y;
|
||||
err_1 -= delta.z;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
current.x += inc.x;
|
||||
err_2 -= delta.z;
|
||||
}
|
||||
err_1 += delta.y;
|
||||
err_2 += delta.x;
|
||||
current.z += inc.z;
|
||||
}
|
||||
inline Ray operator/(float scale) const noexcept {
|
||||
return Ray(from / scale, dir, dist / scale);
|
||||
}
|
||||
points.push_back(current);
|
||||
}
|
||||
};
|
||||
|
||||
/// Get path points in integer grid
|
||||
/// @note not precise enough
|
||||
inline void grid(std::vector<voxel_pos>& points) const {
|
||||
voxel_pos current = from + glm::vec3(.5f);
|
||||
voxel_pos d = dir * dist;
|
||||
voxel_pos inc = voxel_pos((d.x < 0) ? -1 : 1, (d.y < 0) ? -1 : 1, (d.z < 0) ? -1 : 1);
|
||||
voxel_pos size = glm::abs(d);
|
||||
voxel_pos delta = size << 1ll;
|
||||
|
||||
if ((size.x >= size.y) && (size.x >= size.z)) {
|
||||
int err_1 = delta.y - size.x;
|
||||
int err_2 = delta.z - size.x;
|
||||
points.reserve(size.x + 1);
|
||||
for (int i = 0; i < size.x; i++) {
|
||||
points.push_back(current);
|
||||
if (err_1 > 0) {
|
||||
current.y += inc.y;
|
||||
err_1 -= delta.x;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
current.z += inc.z;
|
||||
err_2 -= delta.x;
|
||||
}
|
||||
err_1 += delta.y;
|
||||
err_2 += delta.z;
|
||||
current.x += inc.x;
|
||||
}
|
||||
} else if ((size.y >= size.x) && (size.y >= size.z)) {
|
||||
int err_1 = delta.x - size.y;
|
||||
int err_2 = delta.z - size.y;
|
||||
points.reserve(size.y + 1);
|
||||
for (int i = 0; i < size.y; i++) {
|
||||
points.push_back(current);
|
||||
if (err_1 > 0) {
|
||||
current.x += inc.x;
|
||||
err_1 -= delta.y;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
current.z += inc.z;
|
||||
err_2 -= delta.y;
|
||||
}
|
||||
err_1 += delta.x;
|
||||
err_2 += delta.z;
|
||||
current.y += inc.y;
|
||||
}
|
||||
} else {
|
||||
int err_1 = delta.y - size.z;
|
||||
int err_2 = delta.x - size.z;
|
||||
points.reserve(size.z + 1);
|
||||
for (int i = 0; i < size.z; i++) {
|
||||
points.push_back(current);
|
||||
if (err_1 > 0) {
|
||||
current.y += inc.y;
|
||||
err_1 -= delta.z;
|
||||
}
|
||||
if (err_2 > 0) {
|
||||
current.x += inc.x;
|
||||
err_2 -= delta.z;
|
||||
}
|
||||
err_1 += delta.y;
|
||||
err_2 += delta.x;
|
||||
current.z += inc.z;
|
||||
}
|
||||
}
|
||||
points.push_back(current);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,126 +8,128 @@
|
|||
#include <condition_variable>
|
||||
#include <algorithm>
|
||||
|
||||
/// Thread safe queue with unique keys updating priority and value
|
||||
template <class K, class V, class W>
|
||||
class safe_priority_queue_map {
|
||||
private:
|
||||
static bool cmpByWeight(const std::pair<K, W> &a, const std::pair<K, W> &b) {
|
||||
return a.second < b.second;
|
||||
}
|
||||
namespace data {
|
||||
/// Thread safe queue with unique keys updating priority and value
|
||||
template <class K, class V, class W>
|
||||
class safe_priority_queue_map {
|
||||
private:
|
||||
static bool cmpByWeight(const std::pair<K, W> &a, const std::pair<K, W> &b) {
|
||||
return a.second < b.second;
|
||||
}
|
||||
|
||||
std::vector<std::pair<K, W>> heap;
|
||||
robin_hood::unordered_map<K, V> map;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::vector<std::pair<K, W>> heap;
|
||||
robin_hood::unordered_map<K, V> map;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
public:
|
||||
void push(const K& key, const V& val, const W& weight) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
heap.push_back({key, weight});
|
||||
std::push_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
map.insert_or_assign(key, val);
|
||||
cv.notify_one();
|
||||
}
|
||||
public:
|
||||
void push(const K& key, const V& val, const W& weight) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
heap.push_back({key, weight});
|
||||
std::push_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
map.insert_or_assign(key, val);
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
bool pop(std::pair<K, V>& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
return false;
|
||||
bool pop(std::pair<K, V>& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
return false;
|
||||
|
||||
std::pop_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
const auto priority = heap.back();
|
||||
heap.pop_back();
|
||||
std::pop_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
const auto priority = heap.back();
|
||||
heap.pop_back();
|
||||
|
||||
const auto it = map.find(priority.first);
|
||||
if(it == map.end())
|
||||
return false;
|
||||
const auto it = map.find(priority.first);
|
||||
if(it == map.end())
|
||||
return false;
|
||||
|
||||
out = std::make_pair(it->first, it->second);
|
||||
map.erase(it);
|
||||
return true;
|
||||
}
|
||||
out = std::make_pair(it->first, it->second);
|
||||
map.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return heap.empty();
|
||||
}
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return heap.empty();
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return map.size();
|
||||
}
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return map.size();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/// Thread safe queue with unique keys updating priority
|
||||
template <class K, class W>
|
||||
class safe_priority_queue {
|
||||
private:
|
||||
static bool cmpByWeight(const std::pair<K, W> &a, const std::pair<K, W> &b) {
|
||||
return a.second < b.second;
|
||||
}
|
||||
/// Thread safe queue with unique keys updating priority
|
||||
template <class K, class W>
|
||||
class safe_priority_queue {
|
||||
private:
|
||||
static bool cmpByWeight(const std::pair<K, W> &a, const std::pair<K, W> &b) {
|
||||
return a.second < b.second;
|
||||
}
|
||||
|
||||
std::vector<std::pair<K, W>> heap;
|
||||
robin_hood::unordered_set<K> set;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::vector<std::pair<K, W>> heap;
|
||||
robin_hood::unordered_set<K> set;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
public:
|
||||
void push(const K& key, const W& weight) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
heap.push_back({key, weight});
|
||||
std::push_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
set.insert(key);
|
||||
cv.notify_one();
|
||||
}
|
||||
public:
|
||||
void push(const K& key, const W& weight) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
heap.push_back({key, weight});
|
||||
std::push_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
set.insert(key);
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
bool pop(K& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
return false;
|
||||
bool pop(K& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
return false;
|
||||
|
||||
std::pop_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
const auto priority = heap.back();
|
||||
heap.pop_back();
|
||||
std::pop_heap(heap.begin(), heap.end(), cmpByWeight);
|
||||
const auto priority = heap.back();
|
||||
heap.pop_back();
|
||||
|
||||
const auto it = set.find(priority.first);
|
||||
if(it == set.end())
|
||||
return false;
|
||||
const auto it = set.find(priority.first);
|
||||
if(it == set.end())
|
||||
return false;
|
||||
|
||||
out = *it;
|
||||
set.erase(it);
|
||||
return true;
|
||||
}
|
||||
out = *it;
|
||||
set.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return heap.empty();
|
||||
}
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return heap.empty();
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return set.size();
|
||||
}
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return set.size();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (heap.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,49 +4,51 @@
|
|||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
/// Thread safe queue
|
||||
template <class T>
|
||||
class safe_queue {
|
||||
private:
|
||||
std::queue<T> queue;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
namespace data {
|
||||
/// Thread safe queue
|
||||
template <class T>
|
||||
class safe_queue {
|
||||
private:
|
||||
std::queue<T> queue;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
public:
|
||||
void push(const T& in) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
queue.push(in);
|
||||
cv.notify_one();
|
||||
}
|
||||
public:
|
||||
void push(const T& in) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
queue.push(in);
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
bool pop(T& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
bool pop(T& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
|
||||
out = queue.front();
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
out = queue.front();
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return queue.empty();
|
||||
}
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return queue.empty();
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return queue.size();
|
||||
}
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if(queue.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if(queue.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,69 +5,71 @@
|
|||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
/// Thread safe queue discarding duplicate values
|
||||
template <class T>
|
||||
class safe_unique_queue {
|
||||
private:
|
||||
std::queue<T> queue;
|
||||
std::unordered_set<T> set;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
namespace data {
|
||||
/// Thread safe queue discarding duplicate values
|
||||
template <class T>
|
||||
class safe_unique_queue {
|
||||
private:
|
||||
std::queue<T> queue;
|
||||
std::unordered_set<T> set;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
|
||||
public:
|
||||
bool push(const T& in) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if(set.insert(in).second) {
|
||||
queue.push(in);
|
||||
cv.notify_one();
|
||||
public:
|
||||
bool push(const T& in) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if(set.insert(in).second) {
|
||||
queue.push(in);
|
||||
cv.notify_one();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pop(T& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
|
||||
out = queue.front();
|
||||
set.erase(out);
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pop(T& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
bool take(T& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
|
||||
out = queue.front();
|
||||
set.erase(out);
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
out = queue.front();
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool take(T& out) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (queue.empty())
|
||||
return false;
|
||||
void release(const T& taken) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
set.erase(taken);
|
||||
}
|
||||
|
||||
out = queue.front();
|
||||
queue.pop();
|
||||
return true;
|
||||
}
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return queue.empty();
|
||||
}
|
||||
|
||||
void release(const T& taken) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
set.erase(taken);
|
||||
}
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return set.size();
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return queue.empty();
|
||||
}
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
size_t size() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
return set.size();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if(queue.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
};
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if(queue.empty())
|
||||
cv.wait(lock);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,39 +1,38 @@
|
|||
#ifndef UNIQUE_QUEUE_HPP
|
||||
#define UNIQUE_QUEUE_HPP
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
#include <cassert>
|
||||
|
||||
/// Queue discarding duplicate values
|
||||
/// @note not thread safe
|
||||
template <class T>
|
||||
struct unique_queue {
|
||||
std::queue<T> queue;
|
||||
std::unordered_set<T> set;
|
||||
namespace data {
|
||||
/// Queue discarding duplicate values
|
||||
/// @note not thread safe
|
||||
template <class T>
|
||||
struct unique_queue {
|
||||
std::queue<T> queue;
|
||||
std::unordered_set<T> set;
|
||||
|
||||
bool push(T in) {
|
||||
if(set.insert(in).second) {
|
||||
queue.push(in);
|
||||
return true;
|
||||
bool push(T in) {
|
||||
if(set.insert(in).second) {
|
||||
queue.push(in);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
T pop() {
|
||||
const auto out = queue.front();
|
||||
set.erase(out);
|
||||
queue.pop();
|
||||
return out;
|
||||
}
|
||||
T pop() {
|
||||
const auto out = queue.front();
|
||||
set.erase(out);
|
||||
queue.pop();
|
||||
return out;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return queue.empty();
|
||||
}
|
||||
bool empty() const {
|
||||
return queue.empty();
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return queue.size();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
size_t size() const {
|
||||
return queue.size();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
22
src/main.cpp
22
src/main.cpp
|
@ -19,10 +19,10 @@
|
|||
|
||||
#include "render/Renderer.hpp"
|
||||
#include "render/pass/ColorProgram.hpp"
|
||||
#include "render/buffer/ColorBuffer.hpp"
|
||||
#include "world/World.hpp"
|
||||
#include "render/buffer/Colored.hpp"
|
||||
#include "world/Universe.hpp"
|
||||
|
||||
#include "data/state.h"
|
||||
#include "state.h"
|
||||
|
||||
#include <Remotery.h>
|
||||
|
||||
|
@ -46,10 +46,10 @@ int main(int, char *[]){
|
|||
renderer->LightInvDir = glm::vec3(-0.5f, 2, -2);
|
||||
UI::setup(window);
|
||||
|
||||
GLuint aimTexture = Program::loadTexture("ui/Aim", false);
|
||||
GLuint aimTexture = pass::Program::loadTexture("ui/Aim", false);
|
||||
|
||||
ColorProgram *lookProgram = new ColorProgram();
|
||||
ColorBuffer lookBuffer(GL_LINES, 24, {
|
||||
pass::ColorProgram *lookProgram = new pass::ColorProgram();
|
||||
buffer::Colored lookBuffer(GL_LINES, 24, {
|
||||
glm::vec3(0, 0, 0), glm::vec3(0, 0, 1),
|
||||
glm::vec3(0, 0, 1), glm::vec3(0, 1, 1),
|
||||
glm::vec3(0, 1, 1), glm::vec3(0, 1, 0),
|
||||
|
@ -84,7 +84,7 @@ int main(int, char *[]){
|
|||
std::cout << "Profiling !" << std::endl;
|
||||
#endif
|
||||
|
||||
World world = World(options.world);
|
||||
world::Universe world = world::Universe(options.world);
|
||||
world.setContouring(contouring::load(options.contouring_idx, options.contouring_data));
|
||||
state.contouring = world.getContouring();
|
||||
|
||||
|
@ -103,9 +103,9 @@ int main(int, char *[]){
|
|||
state.look_at = world.raycast(camera.getRay() / options.voxel_size);
|
||||
if (state.capture_mouse && state.look_at.has_value()) {
|
||||
if (inputs.isPressing(Mouse::Left))
|
||||
world.setCube(state.look_at.value().first, Voxel{0, 0}, options.tool.radius);
|
||||
world.setCube(state.look_at.value().first, world::Voxel{0, 0}, options.tool.radius);
|
||||
else if (inputs.isPressing(Mouse::Right))
|
||||
world.setCube(state.look_at.value().first, Voxel{UCHAR_MAX, options.tool.material}, options.tool.radius);
|
||||
world.setCube(state.look_at.value().first, world::Voxel{UCHAR_MAX, options.tool.material}, options.tool.radius);
|
||||
}
|
||||
world.update(state.position / options.voxel_size, reports.world);
|
||||
inputs.saveKeys();
|
||||
|
@ -157,8 +157,8 @@ int main(int, char *[]){
|
|||
auto pass = renderer->getPass();
|
||||
pass.start();
|
||||
|
||||
std::vector<std::pair<glm::mat4, Buffer *const>> models;
|
||||
std::optional<Frustum> frustum;
|
||||
std::vector<std::pair<glm::mat4, buffer::Abstract *const>> models;
|
||||
std::optional<geometry::Frustum> frustum;
|
||||
if(options.culling) {
|
||||
frustum = {camera.getFrustum()};
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ Renderer::Renderer(const Renderer::options& options) {
|
|||
glGenVertexArrays(1, &VertexArrayID);
|
||||
glBindVertexArray(VertexArrayID);
|
||||
|
||||
MainPass = new MainProgram(options.main);
|
||||
SkyPass = new SkyProgram();
|
||||
MainPass = new pass::MainProgram(options.main);
|
||||
SkyPass = new pass::SkyProgram();
|
||||
SkyEnable = options.skybox;
|
||||
|
||||
FogColor = glm::vec3(options.clear_color.x, options.clear_color.y, options.clear_color.z);
|
||||
|
@ -22,9 +22,9 @@ Renderer::~Renderer() {
|
|||
glDeleteVertexArrays(1, &VertexArrayID);
|
||||
}
|
||||
|
||||
PassContext Renderer::getPass() {
|
||||
pass::Context Renderer::getPass() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
return PassContext(this, MainPass);
|
||||
return pass::Context(this, MainPass);
|
||||
}
|
||||
void Renderer::postProcess() {
|
||||
if(SkyEnable) {
|
||||
|
@ -32,9 +32,9 @@ void Renderer::postProcess() {
|
|||
}
|
||||
}
|
||||
|
||||
void Renderer::reloadShaders(const MainProgram::options& options) {
|
||||
void Renderer::reloadShaders(const pass::MainProgram::options& options) {
|
||||
delete MainPass;
|
||||
MainPass = new MainProgram(options);
|
||||
MainPass = new pass::MainProgram(options);
|
||||
}
|
||||
void Renderer::reloadTextures(const std::string& texturePath, float mipMapLOD) {
|
||||
unloadTextures();
|
||||
|
@ -48,14 +48,14 @@ void Renderer::unloadTextures() {
|
|||
}
|
||||
void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD) {
|
||||
std::vector<std::string> terrainTextures;
|
||||
for(const auto texture: materials::textures) {
|
||||
for(const auto texture: world::materials::textures) {
|
||||
terrainTextures.push_back(texturePath + "/terrain/" + texture);
|
||||
}
|
||||
TextureAtlas = Program::loadTextureArray(terrainTextures, "", mipMapLOD);
|
||||
NormalAtlas = Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD);
|
||||
HOSAtlas = Program::loadTextureArray(terrainTextures, ".hos", mipMapLOD);
|
||||
TextureAtlas = pass::Program::loadTextureArray(terrainTextures, "", mipMapLOD);
|
||||
NormalAtlas = pass::Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD);
|
||||
HOSAtlas = pass::Program::loadTextureArray(terrainTextures, ".hos", mipMapLOD);
|
||||
|
||||
Skybox = Program::loadTextureCube(texturePath + "/sky/Space_tray");
|
||||
Skybox = pass::Program::loadTextureCube(texturePath + "/sky/Space_tray");
|
||||
}
|
||||
|
||||
void Renderer::lookFrom(const Camera& camera) {
|
||||
|
|
|
@ -4,18 +4,25 @@
|
|||
#include <imgui.h>
|
||||
#include "pass/MainProgram.hpp"
|
||||
#include "pass/SkyProgram.hpp"
|
||||
#include "pass/PassContext.hpp"
|
||||
#include "pass/Context.hpp"
|
||||
|
||||
class Camera;
|
||||
/// Handle rendering passes and params
|
||||
class Renderer {
|
||||
public:
|
||||
/// Rendering options
|
||||
struct options {
|
||||
MainProgram::options main;
|
||||
/// Main pass
|
||||
pass::MainProgram::options main;
|
||||
/// Display skybox
|
||||
bool skybox = false;
|
||||
/// Display only wires
|
||||
bool wireframe = false;
|
||||
/// Texture pack name
|
||||
std::string textures = "1024-realistic";
|
||||
/// Textures quality
|
||||
float mipMapLOD = -.5;
|
||||
/// Depth color
|
||||
ImVec4 clear_color;
|
||||
};
|
||||
|
||||
|
@ -52,18 +59,21 @@ public:
|
|||
return Skybox;
|
||||
}
|
||||
|
||||
PassContext getPass();
|
||||
/// Get main pass with context
|
||||
pass::Context getPass();
|
||||
/// Apply postprocessing
|
||||
void postProcess();
|
||||
|
||||
/// Apply camera matrices
|
||||
void lookFrom(const Camera&);
|
||||
void reloadShaders(const MainProgram::options&);
|
||||
void reloadShaders(const pass::MainProgram::options &);
|
||||
void reloadTextures(const std::string &, float mipMapLOD = 0);
|
||||
|
||||
private:
|
||||
GLuint VertexArrayID;
|
||||
|
||||
MainProgram *MainPass;
|
||||
SkyProgram *SkyPass;
|
||||
pass::MainProgram *MainPass;
|
||||
pass::SkyProgram *SkyPass;
|
||||
|
||||
glm::mat4 ProjectionMatrix;
|
||||
glm::mat4 ViewMatrix;
|
||||
|
|
|
@ -160,16 +160,16 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
if (options.editor_show) {
|
||||
ImGui::Begin("Editor", &options.editor_show, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if (state.look_at.has_value()) {
|
||||
ImGui::Text("Look at: (%lld, %lld, %lld) (%s, %.1f)", state.look_at.value().first.x, state.look_at.value().first.y, state.look_at.value().first.z, materials::textures[state.look_at.value().second.Material].c_str(), state.look_at.value().second.Density * 1. / UCHAR_MAX);
|
||||
ImGui::Text("Look at: (%lld, %lld, %lld) (%s, %.1f)", state.look_at.value().first.x, state.look_at.value().first.y, state.look_at.value().first.z, world::materials::textures[state.look_at.value().second.Material].c_str(), state.look_at.value().second.Density * 1. / UCHAR_MAX);
|
||||
ImGui::Text("(%.3f, %.3f, %.3f)", state.look_at.value().first.x * options.voxel_size, state.look_at.value().first.y * options.voxel_size, state.look_at.value().first.z * options.voxel_size);
|
||||
} else {
|
||||
ImGui::Text("Look at: none");
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginCombo("Material", materials::textures[options.tool.material].c_str())) {
|
||||
for (size_t i = 0; i < materials::textures.size(); i++) {
|
||||
if (ImGui::BeginCombo("Material", world::materials::textures[options.tool.material].c_str())) {
|
||||
for (size_t i = 0; i < world::materials::textures.size(); i++) {
|
||||
const bool is_selected = (options.tool.material == i);
|
||||
if (ImGui::Selectable(materials::textures[i].c_str(), is_selected))
|
||||
if (ImGui::Selectable(world::materials::textures[i].c_str(), is_selected))
|
||||
options.tool.material = i;
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
#include "imgui.h"
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "../data/state.h"
|
||||
#include "../state.h"
|
||||
|
||||
namespace UI {
|
||||
/// Retro actions to state
|
||||
enum class Actions {
|
||||
None = 0,
|
||||
FPS = 1 << 0,
|
||||
|
@ -24,10 +25,15 @@ namespace UI {
|
|||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
}
|
||||
|
||||
/// Prepare UI
|
||||
void setup(GLFWwindow*);
|
||||
/// Release UI
|
||||
void unload();
|
||||
/// Compute UI
|
||||
Actions draw(options&, state&, const reports&, GLuint aim);
|
||||
|
||||
/// Is UI in focus
|
||||
bool isFocus();
|
||||
/// Display UI
|
||||
void render();
|
||||
};
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#include "Buffer.hpp"
|
||||
#include "Abstract.hpp"
|
||||
|
||||
Buffer::Buffer(GLenum shape): Shape(shape) {
|
||||
using namespace buffer;
|
||||
|
||||
Abstract::Abstract(GLenum shape): Shape(shape) {
|
||||
glGenBuffers(1, &VertexBufferID);
|
||||
}
|
||||
|
||||
Buffer::~Buffer() {
|
||||
Abstract::~Abstract() {
|
||||
glDeleteBuffers(1, &VertexBufferID);
|
||||
}
|
||||
|
||||
void Buffer::enableVertexAttrib() {
|
||||
void Abstract::enableVertexAttrib() {
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
|
||||
glVertexAttribPointer(
|
||||
|
@ -20,17 +22,17 @@ void Buffer::enableVertexAttrib() {
|
|||
(void *)0 // array buffer offset
|
||||
);
|
||||
}
|
||||
void Buffer::enableAllAttribs() {
|
||||
void Abstract::enableAllAttribs() {
|
||||
enableVertexAttrib();
|
||||
}
|
||||
void Buffer::disableVertexAttrib() {
|
||||
void Abstract::disableVertexAttrib() {
|
||||
glDisableVertexAttribArray(0);
|
||||
}
|
||||
void Buffer::disableAllAttribs() {
|
||||
void Abstract::disableAllAttribs() {
|
||||
disableVertexAttrib();
|
||||
}
|
||||
|
||||
void Buffer::setVertices(const unsigned long size, const void *data) {
|
||||
void Abstract::setVertices(const unsigned long size, const void *data) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace buffer {
|
||||
/// Draw options
|
||||
struct params {
|
||||
/// Bind only vertices positions
|
||||
bool vertexOnly;
|
||||
};
|
||||
|
||||
/// Abstract OpenGL Buffer
|
||||
class Abstract {
|
||||
public:
|
||||
Abstract(GLenum shape);
|
||||
virtual ~Abstract();
|
||||
|
||||
/// Bind and draw buffer
|
||||
virtual uint draw(params params) = 0;
|
||||
|
||||
protected:
|
||||
GLenum Shape;
|
||||
|
||||
GLuint VertexBufferID;
|
||||
|
||||
void enableVertexAttrib();
|
||||
void disableVertexAttrib();
|
||||
void enableAllAttribs();
|
||||
void disableAllAttribs();
|
||||
|
||||
void setVertices(const unsigned long size, const void *data);
|
||||
};
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/// Abstract OpenGL Buffer
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer(GLenum shape);
|
||||
virtual ~Buffer();
|
||||
|
||||
struct params {
|
||||
bool vertexOnly;
|
||||
};
|
||||
|
||||
virtual uint draw(params params) = 0;
|
||||
|
||||
protected:
|
||||
GLenum Shape;
|
||||
|
||||
GLuint VertexBufferID;
|
||||
|
||||
void enableVertexAttrib();
|
||||
void disableVertexAttrib();
|
||||
void enableAllAttribs();
|
||||
void disableAllAttribs();
|
||||
|
||||
void setVertices(const unsigned long size, const void *data);
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Buffer.hpp"
|
||||
|
||||
/// OpenGL VertexBuffer with Colors
|
||||
class ColorBuffer: public Buffer {
|
||||
public:
|
||||
ColorBuffer(GLenum shape, const unsigned long count, const std::vector<glm::vec3> &vertices, const std::vector<glm::vec4> &colors);
|
||||
virtual ~ColorBuffer();
|
||||
|
||||
void enableAllAttribs();
|
||||
void disableAllAttribs();
|
||||
|
||||
uint draw(params params) override;
|
||||
|
||||
private:
|
||||
unsigned long ElementCount;
|
||||
|
||||
GLuint ColorBufferID;
|
||||
|
||||
void setColors(const unsigned long size, const void *data);
|
||||
};
|
|
@ -1,16 +1,18 @@
|
|||
#include "ColorBuffer.hpp"
|
||||
#include "Colored.hpp"
|
||||
|
||||
ColorBuffer::ColorBuffer(GLenum shape, const unsigned long count, const std::vector<glm::vec3> &vertices, const std::vector<glm::vec4> &colors): Buffer(shape) {
|
||||
using namespace buffer;
|
||||
|
||||
Colored::Colored(GLenum shape, const unsigned long count, const std::vector<glm::vec3> &vertices, const std::vector<glm::vec4> &colors): Abstract(shape) {
|
||||
glGenBuffers(1, &ColorBufferID);
|
||||
setVertices(vertices.size() * sizeof(glm::vec3), &vertices[0]);
|
||||
setColors(colors.size() * sizeof(glm::vec4), &colors[0]);
|
||||
ElementCount = count;
|
||||
}
|
||||
ColorBuffer::~ColorBuffer() {
|
||||
Colored::~Colored() {
|
||||
glDeleteBuffers(1, &ColorBufferID);
|
||||
}
|
||||
|
||||
uint ColorBuffer::draw(params params) {
|
||||
uint Colored::draw(params params) {
|
||||
if (params.vertexOnly) {
|
||||
enableVertexAttrib();
|
||||
} else {
|
||||
|
@ -26,7 +28,7 @@ uint ColorBuffer::draw(params params) {
|
|||
return ElementCount;
|
||||
}
|
||||
|
||||
void ColorBuffer::enableAllAttribs() {
|
||||
void Colored::enableAllAttribs() {
|
||||
enableVertexAttrib();
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
|
@ -40,13 +42,13 @@ void ColorBuffer::enableAllAttribs() {
|
|||
(void *)0 // array buffer offset
|
||||
);
|
||||
}
|
||||
void ColorBuffer::disableAllAttribs() {
|
||||
void Colored::disableAllAttribs() {
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
disableVertexAttrib();
|
||||
}
|
||||
|
||||
void ColorBuffer::setColors(const unsigned long size, const void *data) {
|
||||
void Colored::setColors(const unsigned long size, const void *data) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ColorBufferID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Abstract.hpp"
|
||||
|
||||
namespace buffer {
|
||||
/// OpenGL VertexBuffer with Colors
|
||||
class Colored: public Abstract {
|
||||
public:
|
||||
Colored(GLenum shape, const unsigned long count, const std::vector<glm::vec3> &vertices, const std::vector<glm::vec4> &colors);
|
||||
virtual ~Colored();
|
||||
|
||||
void enableAllAttribs();
|
||||
void disableAllAttribs();
|
||||
|
||||
uint draw(params params) override;
|
||||
|
||||
private:
|
||||
unsigned long ElementCount;
|
||||
|
||||
GLuint ColorBufferID;
|
||||
|
||||
void setColors(const unsigned long size, const void *data);
|
||||
};
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
#include "ShortIndexedBuffer.hpp"
|
||||
#include "ShortIndexed.hpp"
|
||||
|
||||
#include "vboindexer.hpp"
|
||||
|
||||
ShortIndexedBuffer::Data::Data(const std::vector<VertexData> &vs, const std::vector<GLushort> &indices): indices(indices) {
|
||||
using namespace buffer;
|
||||
|
||||
ShortIndexed::Data::Data(const std::vector<VertexData> &vs, const std::vector<GLushort> &indices): indices(indices) {
|
||||
vertices.reserve(vs.size());
|
||||
materials.reserve(vs.size());
|
||||
normals.reserve(vs.size());
|
||||
|
@ -12,27 +14,27 @@ ShortIndexedBuffer::Data::Data(const std::vector<VertexData> &vs, const std::vec
|
|||
normals.push_back(vertex.Normal);
|
||||
}
|
||||
}
|
||||
void ShortIndexedBuffer::Data::index(const std::vector<VertexData>& vs) {
|
||||
void ShortIndexed::Data::index(const std::vector<VertexData>& vs) {
|
||||
indexVBO(vs, indices, vertices, materials, normals);
|
||||
}
|
||||
|
||||
ShortIndexedBuffer::ShortIndexedBuffer(GLenum shape, const std::vector<VertexData> &vertices): Buffer(shape) {
|
||||
setData(ShortIndexedBuffer::Data(vertices));
|
||||
ShortIndexed::ShortIndexed(GLenum shape, const std::vector<VertexData> &vertices): Abstract(shape) {
|
||||
setData(ShortIndexed::Data(vertices));
|
||||
}
|
||||
ShortIndexedBuffer::ShortIndexedBuffer(GLenum shape, const std::vector<VertexData> &vertices, const std::vector<GLushort>& indices): Buffer(shape) {
|
||||
setData(ShortIndexedBuffer::Data(vertices, indices));
|
||||
ShortIndexed::ShortIndexed(GLenum shape, const std::vector<VertexData> &vertices, const std::vector<GLushort>& indices): Abstract(shape) {
|
||||
setData(ShortIndexed::Data(vertices, indices));
|
||||
}
|
||||
ShortIndexedBuffer::ShortIndexedBuffer(GLenum shape, const ShortIndexedBuffer::Data &data): Buffer(shape) {
|
||||
ShortIndexed::ShortIndexed(GLenum shape, const ShortIndexed::Data &data): Abstract(shape) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
ShortIndexedBuffer::~ShortIndexedBuffer() {
|
||||
ShortIndexed::~ShortIndexed() {
|
||||
glDeleteBuffers(1, &NormalBufferID);
|
||||
glDeleteBuffers(1, &MaterialBufferID);
|
||||
glDeleteBuffers(1, &IndexBufferID);
|
||||
}
|
||||
|
||||
void ShortIndexedBuffer::enableAllAttribs() {
|
||||
void ShortIndexed::enableAllAttribs() {
|
||||
enableVertexAttrib();
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
|
@ -56,16 +58,16 @@ void ShortIndexedBuffer::enableAllAttribs() {
|
|||
(void *)0 // array buffer offset
|
||||
);
|
||||
}
|
||||
void ShortIndexedBuffer::disableAllAttribs() {
|
||||
void ShortIndexed::disableAllAttribs() {
|
||||
glDisableVertexAttribArray(2);
|
||||
glDisableVertexAttribArray(1);
|
||||
disableVertexAttrib();
|
||||
}
|
||||
void ShortIndexedBuffer::enableIndex() {
|
||||
void ShortIndexed::enableIndex() {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
|
||||
}
|
||||
|
||||
uint ShortIndexedBuffer::draw(Buffer::params params) {
|
||||
uint ShortIndexed::draw(buffer::params params) {
|
||||
if(IndexSize == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -86,7 +88,7 @@ uint ShortIndexedBuffer::draw(Buffer::params params) {
|
|||
}
|
||||
|
||||
#include <iostream>
|
||||
void ShortIndexedBuffer::setData(const ShortIndexedBuffer::Data& data) {
|
||||
void ShortIndexed::setData(const ShortIndexed::Data& data) {
|
||||
glGenBuffers(1, &IndexBufferID);
|
||||
glGenBuffers(1, &MaterialBufferID);
|
||||
glGenBuffers(1, &NormalBufferID);
|
||||
|
@ -101,15 +103,15 @@ void ShortIndexedBuffer::setData(const ShortIndexedBuffer::Data& data) {
|
|||
setNormals(data.normals.size() * sizeof(glm::vec3), &data.normals[0]);
|
||||
}
|
||||
|
||||
void ShortIndexedBuffer::setIndicies(const unsigned long size, const void *data) {
|
||||
void ShortIndexed::setIndicies(const unsigned long size, const void *data) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, IndexBufferID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
}
|
||||
void ShortIndexedBuffer::setMaterials(const unsigned long size, const void *data) {
|
||||
void ShortIndexed::setMaterials(const unsigned long size, const void *data) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, MaterialBufferID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
}
|
||||
void ShortIndexedBuffer::setNormals(const unsigned long size, const void *data) {
|
||||
void ShortIndexed::setNormals(const unsigned long size, const void *data) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, NormalBufferID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "Abstract.hpp"
|
||||
#include "VertexData.hpp"
|
||||
|
||||
namespace buffer {
|
||||
/// OpenGL VertexBuffer with IndexBuffer
|
||||
class ShortIndexed: public Abstract {
|
||||
public:
|
||||
/// Preindexed buffer data
|
||||
struct Data {
|
||||
std::vector<GLushort> indices;
|
||||
std::vector<glm::vec3> vertices;
|
||||
std::vector<GLushort> materials;
|
||||
std::vector<glm::vec3> normals;
|
||||
|
||||
Data() { }
|
||||
Data(const std::vector<VertexData> &vertices, const std::vector<GLushort> &indices);
|
||||
Data(const std::vector<VertexData> &vertices) { index(vertices); }
|
||||
|
||||
void index(const std::vector<VertexData> &vertices);
|
||||
bool empty() const {
|
||||
return indices.empty();
|
||||
}
|
||||
void clear() {
|
||||
indices.clear();
|
||||
vertices.clear();
|
||||
materials.clear();
|
||||
normals.clear();
|
||||
}
|
||||
};
|
||||
|
||||
ShortIndexed(GLenum shape, const typename std::vector<VertexData> &vertices);
|
||||
ShortIndexed(GLenum shape, const typename std::vector<VertexData> &vertices, const typename std::vector<GLushort> &indices);
|
||||
ShortIndexed(GLenum shape, const typename ShortIndexed::Data &data);
|
||||
virtual ~ShortIndexed();
|
||||
|
||||
void enableAllAttribs();
|
||||
void disableAllAttribs();
|
||||
void enableIndex();
|
||||
|
||||
uint draw(params params) override;
|
||||
|
||||
private:
|
||||
GLuint IndexBufferID;
|
||||
GLushort IndexSize = 0;
|
||||
|
||||
GLuint MaterialBufferID;
|
||||
GLuint NormalBufferID;
|
||||
|
||||
void setData(const ShortIndexed::Data &data);
|
||||
|
||||
void setIndicies(const unsigned long size, const void *data);
|
||||
void setMaterials(const unsigned long size, const void *data);
|
||||
void setNormals(const unsigned long size, const void *data);
|
||||
};
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "Buffer.hpp"
|
||||
#include "VertexData.hpp"
|
||||
|
||||
/// OpenGL VertexBuffer with IndexBuffer
|
||||
class ShortIndexedBuffer: public Buffer {
|
||||
public:
|
||||
struct Data {
|
||||
std::vector<GLushort> indices;
|
||||
std::vector<glm::vec3> vertices;
|
||||
std::vector<GLushort> materials;
|
||||
std::vector<glm::vec3> normals;
|
||||
|
||||
Data() { }
|
||||
Data(const std::vector<VertexData> &vertices, const std::vector<GLushort> &indices);
|
||||
Data(const std::vector<VertexData> &vertices) { index(vertices); }
|
||||
|
||||
void index(const std::vector<VertexData> &vertices);
|
||||
bool empty() const {
|
||||
return indices.empty();
|
||||
}
|
||||
void clear() {
|
||||
indices.clear();
|
||||
vertices.clear();
|
||||
materials.clear();
|
||||
normals.clear();
|
||||
}
|
||||
};
|
||||
|
||||
ShortIndexedBuffer(GLenum shape, const typename std::vector<VertexData> &vertices);
|
||||
ShortIndexedBuffer(GLenum shape, const typename std::vector<VertexData> &vertices, const typename std::vector<GLushort> &indices);
|
||||
ShortIndexedBuffer(GLenum shape, const typename ShortIndexedBuffer::Data &data);
|
||||
virtual ~ShortIndexedBuffer();
|
||||
|
||||
void enableAllAttribs();
|
||||
void disableAllAttribs();
|
||||
void enableIndex();
|
||||
|
||||
uint draw(Buffer::params params) override;
|
||||
|
||||
private:
|
||||
GLuint IndexBufferID;
|
||||
GLushort IndexSize = 0;
|
||||
|
||||
GLuint MaterialBufferID;
|
||||
GLuint NormalBufferID;
|
||||
|
||||
void setData(const ShortIndexedBuffer::Data &data);
|
||||
|
||||
void setIndicies(const unsigned long size, const void *data);
|
||||
void setMaterials(const unsigned long size, const void *data);
|
||||
void setNormals(const unsigned long size, const void *data);
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#include "Vertex.hpp"
|
||||
|
||||
using namespace buffer;
|
||||
|
||||
Vertex::Vertex(GLenum shape, const unsigned long count, const unsigned long size, const void *data): Abstract(shape) {
|
||||
setVertices(size, data);
|
||||
ElementCount = count;
|
||||
}
|
||||
|
||||
uint Vertex::draw(params) {
|
||||
enableAllAttribs();
|
||||
glDrawArrays(Shape, 0, ElementCount);
|
||||
disableAllAttribs();
|
||||
return ElementCount;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "Abstract.hpp"
|
||||
|
||||
/// OpenGL VertexBuffer
|
||||
namespace buffer {
|
||||
class Vertex: public Abstract {
|
||||
public:
|
||||
Vertex(GLenum shape, const unsigned long count, const unsigned long size, const void *data);
|
||||
|
||||
uint draw(params) override;
|
||||
|
||||
private:
|
||||
unsigned long ElementCount;
|
||||
};
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include "VertexBuffer.hpp"
|
||||
|
||||
VertexBuffer::VertexBuffer(GLenum shape, const unsigned long count, const unsigned long size, const void *data): Buffer(shape) {
|
||||
setVertices(size, data);
|
||||
ElementCount = count;
|
||||
}
|
||||
|
||||
uint VertexBuffer::draw(params) {
|
||||
enableAllAttribs();
|
||||
glDrawArrays(Shape, 0, ElementCount);
|
||||
disableAllAttribs();
|
||||
return ElementCount;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "Buffer.hpp"
|
||||
|
||||
/// OpenGL VertexBuffer
|
||||
class VertexBuffer: public Buffer {
|
||||
public:
|
||||
VertexBuffer(GLenum shape, const unsigned long count, const unsigned long size, const void *data);
|
||||
|
||||
uint draw(params) override;
|
||||
|
||||
private:
|
||||
unsigned long ElementCount;
|
||||
};
|
|
@ -1,18 +1,17 @@
|
|||
#ifndef VERTEX_DATA_HPP
|
||||
#define VERTEX_DATA_HPP
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <string.h> // for memcmp
|
||||
#include <GL/glew.h>
|
||||
|
||||
/// Vertex properties
|
||||
struct VertexData {
|
||||
glm::vec3 Position;
|
||||
GLushort Material;
|
||||
glm::vec3 Normal;
|
||||
bool operator<(const VertexData that) const {
|
||||
return memcmp((void *)this, (void *)&that, sizeof(VertexData)) > 0;
|
||||
namespace buffer {
|
||||
/// Vertex properties
|
||||
struct VertexData {
|
||||
glm::vec3 Position;
|
||||
GLushort Material;
|
||||
glm::vec3 Normal;
|
||||
bool operator<(const VertexData that) const {
|
||||
return memcmp((void *)this, (void *)&that, sizeof(VertexData)) > 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
#include "vboindexer.hpp"
|
||||
|
||||
bool getSimilarVertexIndex_fast(
|
||||
const VertexData &packed,
|
||||
std::map<VertexData, GLushort> &VertexToOutIndex,
|
||||
const buffer::VertexData &packed,
|
||||
std::map<buffer::VertexData, GLushort> &VertexToOutIndex,
|
||||
GLushort &result)
|
||||
{
|
||||
std::map<VertexData, GLushort>::iterator it = VertexToOutIndex.find(packed);
|
||||
std::map<buffer::VertexData, GLushort>::iterator it = VertexToOutIndex.find(packed);
|
||||
if ( it == VertexToOutIndex.end() ){
|
||||
return false;
|
||||
}else{
|
||||
|
@ -19,11 +19,11 @@ bool getSimilarVertexIndex_fast(
|
|||
}
|
||||
}
|
||||
bool getSimilarVertexIndex_fast(
|
||||
const VertexData &packed,
|
||||
std::map<VertexData, unsigned int> &VertexToOutIndex,
|
||||
const buffer::VertexData &packed,
|
||||
std::map<buffer::VertexData, unsigned int> &VertexToOutIndex,
|
||||
unsigned int &result)
|
||||
{
|
||||
std::map<VertexData, unsigned int>::iterator it = VertexToOutIndex.find(packed);
|
||||
std::map<buffer::VertexData, unsigned int>::iterator it = VertexToOutIndex.find(packed);
|
||||
if ( it == VertexToOutIndex.end() ){
|
||||
return false;
|
||||
}else{
|
||||
|
@ -43,13 +43,13 @@ void indexVBO(
|
|||
std::vector<GLushort> &out_materials,
|
||||
std::vector<glm::vec3> &out_normals)
|
||||
{
|
||||
std::map<VertexData,unsigned int> VertexToOutIndex;
|
||||
std::map<buffer::VertexData,unsigned int> VertexToOutIndex;
|
||||
|
||||
out_indices.reserve(in_vertices.size());
|
||||
// For each input vertex
|
||||
for (unsigned int i = 0; i < in_vertices.size(); i++) {
|
||||
|
||||
VertexData packed = {in_vertices[i], in_materials[i], in_normals[i]};
|
||||
buffer::VertexData packed = {in_vertices[i], in_materials[i], in_normals[i]};
|
||||
|
||||
// Try to find a similar vertex in out_XXXX
|
||||
unsigned int index;
|
||||
|
@ -68,14 +68,14 @@ void indexVBO(
|
|||
}
|
||||
}
|
||||
void indexVBO(
|
||||
const std::vector<VertexData> &in_vertices,
|
||||
const std::vector<buffer::VertexData> &in_vertices,
|
||||
|
||||
std::vector<GLushort> &out_indices,
|
||||
std::vector<glm::vec3> &out_vertices,
|
||||
std::vector<GLushort> &out_materials,
|
||||
std::vector<glm::vec3> &out_normals)
|
||||
{
|
||||
std::map<VertexData, GLushort> VertexToOutIndex;
|
||||
std::map<buffer::VertexData, GLushort> VertexToOutIndex;
|
||||
|
||||
out_indices.reserve(in_vertices.size());
|
||||
// For each input vertex
|
||||
|
@ -95,44 +95,4 @@ void indexVBO(
|
|||
VertexToOutIndex[ in_vertices[i] ] = newindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void indexVBO_TBN(
|
||||
std::vector<glm::vec3> & in_vertices,
|
||||
std::vector<glm::vec2> & in_uvs,
|
||||
std::vector<glm::vec3> & in_normals,
|
||||
std::vector<glm::vec3> & in_tangents,
|
||||
std::vector<glm::vec3> & in_bitangents,
|
||||
|
||||
std::vector<unsigned int> & out_indices,
|
||||
std::vector<glm::vec3> & out_vertices,
|
||||
std::vector<glm::vec2> & out_uvs,
|
||||
std::vector<glm::vec3> & out_normals,
|
||||
std::vector<glm::vec3> & out_tangents,
|
||||
std::vector<glm::vec3> & out_bitangents
|
||||
){
|
||||
// For each input vertex
|
||||
for ( unsigned int i=0; i<in_vertices.size(); i++ ){
|
||||
|
||||
// Try to find a similar vertex in out_XXXX
|
||||
unsigned int index;
|
||||
bool found = getSimilarVertexIndex(in_vertices[i], in_uvs[i], in_normals[i], out_vertices, out_uvs, out_normals, index);
|
||||
|
||||
if ( found ){ // A similar vertex is already in the VBO, use it instead !
|
||||
out_indices.push_back( index );
|
||||
|
||||
// Average the tangents and the bitangents
|
||||
out_tangents[index] += in_tangents[i];
|
||||
out_bitangents[index] += in_bitangents[i];
|
||||
}else{ // If not, it needs to be added in the output data.
|
||||
out_vertices.push_back( in_vertices[i]);
|
||||
out_uvs .push_back( in_uvs[i]);
|
||||
out_normals .push_back( in_normals[i]);
|
||||
out_tangents .push_back( in_tangents[i]);
|
||||
out_bitangents .push_back( in_bitangents[i]);
|
||||
out_indices .push_back( (unsigned int)out_vertices.size() - 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -17,7 +17,7 @@ void indexVBO(
|
|||
std::vector<glm::vec3> &out_normals);
|
||||
|
||||
void indexVBO(
|
||||
const std::vector<VertexData> &in_vertices,
|
||||
const std::vector<buffer::VertexData> &in_vertices,
|
||||
|
||||
std::vector<GLushort> &out_indices,
|
||||
std::vector<glm::vec3> &out_vertices,
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "../Renderer.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
ColorProgram::ColorProgram(): Program() {
|
||||
|
||||
std::vector<std::string> flags;
|
||||
|
@ -18,11 +20,11 @@ ColorProgram::~ColorProgram() { }
|
|||
std::string ColorProgram::getName() const {
|
||||
return "Color";
|
||||
}
|
||||
void ColorProgram::start(Renderer *renderer) { }
|
||||
Buffer::params ColorProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
void ColorProgram::start(Renderer *) { }
|
||||
buffer::params ColorProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
const auto mvp = renderer->getProjectionMatrix() * renderer->getViewMatrix() * modelMatrix;
|
||||
setMVP(&mvp[0][0]);
|
||||
return Buffer::params{.vertexOnly = false};
|
||||
return buffer::params{.vertexOnly = false};
|
||||
}
|
||||
|
||||
void ColorProgram::setMVP(const GLfloat *matrix) {
|
||||
|
|
|
@ -2,18 +2,20 @@
|
|||
|
||||
#include "Program.hpp"
|
||||
|
||||
/// Final pass
|
||||
class ColorProgram: public Program {
|
||||
public:
|
||||
ColorProgram();
|
||||
~ColorProgram();
|
||||
namespace pass {
|
||||
/// Solid colors pass
|
||||
class ColorProgram: public Program {
|
||||
public:
|
||||
ColorProgram();
|
||||
~ColorProgram();
|
||||
|
||||
std::string getName() const override;
|
||||
void start(Renderer *) override;
|
||||
Buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
|
||||
std::string getName() const override;
|
||||
void start(Renderer *) override;
|
||||
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
|
||||
|
||||
void setMVP(const GLfloat *matrix);
|
||||
void setMVP(const GLfloat *matrix);
|
||||
|
||||
private:
|
||||
GLuint MVPMatrixID;
|
||||
};
|
||||
private:
|
||||
GLuint MVPMatrixID;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#include "Context.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
Context::Context(Renderer* Renderer, Program *Program):
|
||||
renderer(Renderer), program(Program) { }
|
||||
|
||||
void Context::start() {
|
||||
program->useIt();
|
||||
program->start(renderer);
|
||||
}
|
||||
buffer::params Context::setup(glm::mat4 modelMatrix) {
|
||||
return program->setup(renderer, modelMatrix);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "../buffer/Abstract.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
class Renderer;
|
||||
|
||||
namespace pass {
|
||||
class Program;
|
||||
/// Program execution container
|
||||
struct Context {
|
||||
public:
|
||||
Context(Renderer *Renderer, Program *Program);
|
||||
|
||||
/// Prepare for multiple draw
|
||||
void start();
|
||||
/// Prepare for specific draw
|
||||
buffer::params setup(glm::mat4 modelMatrix);
|
||||
|
||||
private:
|
||||
Renderer *renderer;
|
||||
Program *program;
|
||||
};
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "../Renderer.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
MainProgram::MainProgram(const MainProgram::options& opts): Program() {
|
||||
|
||||
std::vector<std::string> flags;
|
||||
|
@ -47,12 +49,12 @@ void MainProgram::start(Renderer *renderer) {
|
|||
setLightInvDir(&renderer->LightInvDir[0]);
|
||||
setFog(&renderer->FogColor[0], renderer->FogDepth);
|
||||
}
|
||||
Buffer::params MainProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
buffer::params MainProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
setModel(&modelMatrix[0][0]);
|
||||
setView(&renderer->getViewMatrix()[0][0]);
|
||||
const auto mvp = renderer->getProjectionMatrix() * renderer->getViewMatrix() * modelMatrix;
|
||||
setMVP(&mvp[0][0]);
|
||||
return Buffer::params{.vertexOnly = false};
|
||||
return buffer::params{.vertexOnly = false};
|
||||
}
|
||||
|
||||
void MainProgram::setMVP(const GLfloat *matrix) {
|
||||
|
|
|
@ -2,44 +2,51 @@
|
|||
|
||||
#include "Program.hpp"
|
||||
|
||||
/// Final pass
|
||||
class MainProgram: public Program {
|
||||
public:
|
||||
struct options {
|
||||
bool pbr = true;
|
||||
bool triplanar = false;
|
||||
bool blend = true;
|
||||
bool fog = true;
|
||||
namespace pass {
|
||||
/// World voxels pass
|
||||
class MainProgram: public Program {
|
||||
public:
|
||||
/// Pass options
|
||||
struct options {
|
||||
/// Apply light properties
|
||||
bool pbr = true;
|
||||
/// Triplanar texture mapping
|
||||
bool triplanar = false;
|
||||
/// Blend voxel with mixed materials
|
||||
bool blend = true;
|
||||
/// Depth fog
|
||||
bool fog = true;
|
||||
};
|
||||
|
||||
MainProgram(const options &opts);
|
||||
~MainProgram();
|
||||
|
||||
std::string getName() const override;
|
||||
void start(Renderer *) override;
|
||||
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
|
||||
|
||||
void setMVP(const GLfloat *matrix);
|
||||
void setModel(const GLfloat *matrix);
|
||||
void setView(const GLfloat *matrix);
|
||||
|
||||
void bindTexture(const GLuint textureID);
|
||||
void bindNormal(const GLuint textureID);
|
||||
void bindHOS(const GLuint textureID);
|
||||
|
||||
void setLightInvDir(const GLfloat *pos);
|
||||
void setFog(const GLfloat *color, GLfloat depth);
|
||||
|
||||
private:
|
||||
GLuint MVPMatrixID;
|
||||
GLuint ModelMatrixID;
|
||||
GLuint ViewMatrixID;
|
||||
|
||||
GLuint TextureID;
|
||||
GLuint NormalID;
|
||||
GLuint HOSID;
|
||||
|
||||
GLuint LightInvDirID;
|
||||
GLuint FogDepthID;
|
||||
GLuint FogColorID;
|
||||
};
|
||||
|
||||
MainProgram(const options &opts);
|
||||
~MainProgram();
|
||||
|
||||
std::string getName() const override;
|
||||
void start(Renderer *) override;
|
||||
Buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
|
||||
|
||||
void setMVP(const GLfloat *matrix);
|
||||
void setModel(const GLfloat *matrix);
|
||||
void setView(const GLfloat *matrix);
|
||||
|
||||
void bindTexture(const GLuint textureID);
|
||||
void bindNormal(const GLuint textureID);
|
||||
void bindHOS(const GLuint textureID);
|
||||
|
||||
void setLightInvDir(const GLfloat *pos);
|
||||
void setFog(const GLfloat *color, GLfloat depth);
|
||||
|
||||
private:
|
||||
GLuint MVPMatrixID;
|
||||
GLuint ModelMatrixID;
|
||||
GLuint ViewMatrixID;
|
||||
|
||||
GLuint TextureID;
|
||||
GLuint NormalID;
|
||||
GLuint HOSID;
|
||||
|
||||
GLuint LightInvDirID;
|
||||
GLuint FogDepthID;
|
||||
GLuint FogColorID;
|
||||
};
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include "PassContext.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
|
||||
PassContext::PassContext(Renderer* Renderer, Program *Program):
|
||||
renderer(Renderer), program(Program) { }
|
||||
|
||||
void PassContext::start() {
|
||||
program->useIt();
|
||||
program->start(renderer);
|
||||
}
|
||||
Buffer::params PassContext::setup(glm::mat4 modelMatrix) {
|
||||
return program->setup(renderer, modelMatrix);
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../buffer/Buffer.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
class Renderer;
|
||||
class Program;
|
||||
|
||||
/// Program execution container
|
||||
struct PassContext {
|
||||
public:
|
||||
PassContext(Renderer *Renderer, Program *Program);
|
||||
|
||||
void start();
|
||||
Buffer::params setup(glm::mat4 modelMatrix);
|
||||
|
||||
private:
|
||||
Renderer *renderer;
|
||||
Program *program;
|
||||
};
|
|
@ -8,6 +8,8 @@
|
|||
#define SHADER_DIR CONTENT_DIR "shaders/"
|
||||
#define TEXTURES_DIR CONTENT_DIR "textures/"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
void Program::load(const std::vector<Shader*>& shaders) {
|
||||
ProgramID = glCreateProgram();
|
||||
|
||||
|
|
|
@ -6,27 +6,33 @@
|
|||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Shader.hpp"
|
||||
#include "../buffer/Buffer.hpp"
|
||||
#include "../buffer/Abstract.hpp"
|
||||
|
||||
class Renderer;
|
||||
/// OpenGL shaders pipeline
|
||||
class Program {
|
||||
public:
|
||||
virtual ~Program();
|
||||
/// OpenGL programs
|
||||
namespace pass {
|
||||
/// OpenGL shaders pipeline
|
||||
class Program {
|
||||
public:
|
||||
virtual ~Program();
|
||||
|
||||
void useIt();
|
||||
virtual std::string getName() const = 0;
|
||||
/// Bind program
|
||||
void useIt();
|
||||
virtual std::string getName() const = 0;
|
||||
|
||||
virtual void start(Renderer*) = 0;
|
||||
virtual Buffer::params setup(Renderer*, glm::mat4 modelMatrix) = 0;
|
||||
/// Prepare for multiple draw
|
||||
virtual void start(Renderer*) = 0;
|
||||
/// Prepare for specific draw
|
||||
virtual buffer::params setup(Renderer*, glm::mat4 modelMatrix) = 0;
|
||||
|
||||
static GLuint loadTexture(const std::string &name, bool linear = true);
|
||||
static GLuint loadRawTexture(const std::string &name);
|
||||
static GLuint loadTextureArray(const std::vector<std::string> &names, const std::string &suffix = "", float mipMapLOD = 0);
|
||||
static GLuint loadTextureCube(const std::string &name);
|
||||
static GLuint loadTexture(const std::string &name, bool linear = true);
|
||||
static GLuint loadRawTexture(const std::string &name);
|
||||
static GLuint loadTextureArray(const std::vector<std::string> &names, const std::string &suffix = "", float mipMapLOD = 0);
|
||||
static GLuint loadTextureCube(const std::string &name);
|
||||
|
||||
protected:
|
||||
void load(const std::vector<Shader *> &shaders);
|
||||
virtual Shader *loadShader(GLenum type, const std::vector<std::string> &flags = {});
|
||||
GLuint ProgramID;
|
||||
};
|
||||
protected:
|
||||
void load(const std::vector<Shader *> &shaders);
|
||||
virtual Shader *loadShader(GLenum type, const std::vector<std::string> &flags = {});
|
||||
GLuint ProgramID;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace pass;
|
||||
|
||||
Shader::Shader(GLenum type, const std::string& file_path, const std::vector<std::string>& flags) {
|
||||
ShaderID = glCreateShader(type);
|
||||
|
||||
|
|
|
@ -4,32 +4,34 @@
|
|||
#include <vector>
|
||||
#include <GL/glew.h>
|
||||
|
||||
/// OpenGL shader
|
||||
class Shader {
|
||||
public:
|
||||
Shader(GLenum type, const std::string &file_path, const std::vector<std::string> &flags = {});
|
||||
~Shader();
|
||||
namespace pass {
|
||||
/// OpenGL shader
|
||||
class Shader {
|
||||
public:
|
||||
Shader(GLenum type, const std::string &file_path, const std::vector<std::string> &flags = {});
|
||||
~Shader();
|
||||
|
||||
GLuint getId() const {
|
||||
return ShaderID;
|
||||
}
|
||||
|
||||
static std::string getExt(GLenum type) {
|
||||
switch (type) {
|
||||
case GL_VERTEX_SHADER:
|
||||
return "vs";
|
||||
|
||||
case GL_GEOMETRY_SHADER:
|
||||
return "gs";
|
||||
|
||||
case GL_FRAGMENT_SHADER:
|
||||
return "fs";
|
||||
|
||||
default:
|
||||
return "??";
|
||||
GLuint getId() const {
|
||||
return ShaderID;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GLuint ShaderID;
|
||||
};
|
||||
static std::string getExt(GLenum type) {
|
||||
switch (type) {
|
||||
case GL_VERTEX_SHADER:
|
||||
return "vs";
|
||||
|
||||
case GL_GEOMETRY_SHADER:
|
||||
return "gs";
|
||||
|
||||
case GL_FRAGMENT_SHADER:
|
||||
return "fs";
|
||||
|
||||
default:
|
||||
return "??";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GLuint ShaderID;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "../Renderer.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
const GLfloat g_cubemap_vertices[] = {
|
||||
-1.0f, 1.0f, -1.0f,
|
||||
-1.0f, -1.0f, -1.0f,
|
||||
|
@ -70,8 +72,8 @@ void SkyProgram::start(Renderer *renderer) {
|
|||
|
||||
bindTexture(renderer->getSkyTexture());
|
||||
}
|
||||
Buffer::params SkyProgram::setup(Renderer *, glm::mat4) {
|
||||
return Buffer::params{.vertexOnly = true};
|
||||
buffer::params SkyProgram::setup(Renderer *, glm::mat4) {
|
||||
return buffer::params{.vertexOnly = true};
|
||||
}
|
||||
void SkyProgram::draw(Renderer *renderer) {
|
||||
useIt();
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include "Program.hpp"
|
||||
#include "../buffer/VertexBuffer.hpp"
|
||||
#include "../buffer/Vertex.hpp"
|
||||
|
||||
/// Skybox pass
|
||||
class SkyProgram: public Program {
|
||||
public:
|
||||
SkyProgram();
|
||||
~SkyProgram();
|
||||
namespace pass {
|
||||
/// Skybox pass
|
||||
class SkyProgram: public Program {
|
||||
public:
|
||||
SkyProgram();
|
||||
~SkyProgram();
|
||||
|
||||
std::string getName() const override;
|
||||
void start(Renderer *) override;
|
||||
Buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
|
||||
std::string getName() const override;
|
||||
void start(Renderer *) override;
|
||||
buffer::params setup(Renderer *, glm::mat4 modelMatrix) override;
|
||||
|
||||
void draw(Renderer *);
|
||||
/// Direct draw using internal buffer
|
||||
void draw(Renderer *);
|
||||
|
||||
void setView(const GLfloat *matrix);
|
||||
void setProjection(const GLfloat *matrix);
|
||||
void setView(const GLfloat *matrix);
|
||||
void setProjection(const GLfloat *matrix);
|
||||
|
||||
void bindTexture(const GLuint textureID);
|
||||
void bindTexture(const GLuint textureID);
|
||||
|
||||
private:
|
||||
GLuint ViewMatrixID;
|
||||
GLuint ProjectionMatrixID;
|
||||
GLuint TextureID;
|
||||
private:
|
||||
GLuint ViewMatrixID;
|
||||
GLuint ProjectionMatrixID;
|
||||
GLuint TextureID;
|
||||
|
||||
VertexBuffer CubeBuffer;
|
||||
};
|
||||
buffer::Vertex CubeBuffer;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "UIProgram.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
UIProgram::UIProgram() : Program() {
|
||||
std::vector<Shader*> shaders;
|
||||
shaders.push_back(loadShader(GL_VERTEX_SHADER));
|
||||
|
|
|
@ -2,16 +2,18 @@
|
|||
|
||||
#include "Program.hpp"
|
||||
|
||||
/// Basic final pass
|
||||
class UIProgram: public Program {
|
||||
public:
|
||||
UIProgram();
|
||||
~UIProgram();
|
||||
namespace pass {
|
||||
/// To screen texture pass
|
||||
class UIProgram: public Program {
|
||||
public:
|
||||
UIProgram();
|
||||
~UIProgram();
|
||||
|
||||
std::string getName() const override;
|
||||
std::string getName() const override;
|
||||
|
||||
void bindTexture(GLuint textureID);
|
||||
void bindTexture(GLuint textureID);
|
||||
|
||||
private:
|
||||
GLuint TextureID;
|
||||
};
|
||||
private:
|
||||
GLuint TextureID;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include "glm.hpp"
|
||||
#include "circular_buffer.hpp"
|
||||
#include "../render/Renderer.hpp"
|
||||
#include "../world/World.hpp"
|
||||
#include "../control/Camera.hpp"
|
||||
#include "../contouring/index.hpp"
|
||||
#include "data/glm.hpp"
|
||||
#include "data/circular_buffer.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
#include "world/Universe.hpp"
|
||||
#include "control/Camera.hpp"
|
||||
#include "contouring/index.hpp"
|
||||
|
||||
inline ImColor fromHex(const std::string& str) {
|
||||
int rgb[3] = {UCHAR_MAX};
|
||||
|
@ -30,6 +30,7 @@ inline std::string toHexa(const ImVec4& rgba) {
|
|||
/// Savable game options
|
||||
struct options {
|
||||
const char *PATH = "config.toml";
|
||||
/// Load from PATH
|
||||
options() {
|
||||
auto config = std::filesystem::exists(PATH) ? toml::parse_file(PATH) : toml::table();
|
||||
target_fps = config["window"]["fps"].value_or(60);
|
||||
|
@ -76,6 +77,7 @@ struct options {
|
|||
tool.material = config["editor"]["tool"]["material"].value_or<int>(tool.material);
|
||||
tool.radius = config["editor"]["tool"]["radius"].value_or(tool.radius);
|
||||
}
|
||||
/// Write to PATH
|
||||
void save() {
|
||||
auto config = toml::table();
|
||||
config.insert_or_assign("window", toml::table({
|
||||
|
@ -149,7 +151,7 @@ struct options {
|
|||
Renderer::options renderer;
|
||||
|
||||
bool show_debug_world;
|
||||
World::options world;
|
||||
world::Universe::options world;
|
||||
float voxel_size;
|
||||
|
||||
bool show_debug_contouring;
|
||||
|
@ -163,7 +165,7 @@ struct options {
|
|||
bool editor_show;
|
||||
struct tool {
|
||||
int radius = 2;
|
||||
unsigned long long material = 2;
|
||||
unsigned short material = 2;
|
||||
} tool;
|
||||
|
||||
bool overlay_show;
|
||||
|
@ -177,7 +179,7 @@ struct options {
|
|||
struct state {
|
||||
bool capture_mouse = true;
|
||||
camera_pos position;
|
||||
std::optional<std::pair<voxel_pos, Voxel>> look_at = {};
|
||||
std::optional<std::pair<voxel_pos, world::Voxel>> look_at = {};
|
||||
|
||||
std::shared_ptr<contouring::Abstract> contouring;
|
||||
|
||||
|
@ -195,5 +197,5 @@ struct reports {
|
|||
circular_buffer<float> swap = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> wait = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
} main;
|
||||
World::report world;
|
||||
world::Universe::report world;
|
||||
};
|
|
@ -3,6 +3,8 @@
|
|||
#include <FastNoiseSIMD.h>
|
||||
#include "materials.hpp"
|
||||
|
||||
using namespace world;
|
||||
|
||||
#define DENSITY 0.f
|
||||
#define GRANULARITY 30.f
|
||||
|
||||
|
@ -28,6 +30,17 @@ std::optional<Faces> Chunk::update() {
|
|||
}
|
||||
}
|
||||
|
||||
void Chunk::set(ushort idx, const Voxel& val) {
|
||||
voxels[idx] = val;
|
||||
invalidate(
|
||||
((!getNeighborIdx(idx, Face::Up).has_value()) & Faces::Up) |
|
||||
((!getNeighborIdx(idx, Face::Down).has_value()) & Faces::Down) |
|
||||
((!getNeighborIdx(idx, Face::Left).has_value()) & Faces::Left) |
|
||||
((!getNeighborIdx(idx, Face::Right).has_value()) & Faces::Right) |
|
||||
((!getNeighborIdx(idx, Face::Forward).has_value()) & Faces::Forward) |
|
||||
((!getNeighborIdx(idx, Face::Backward).has_value()) & Faces::Backward));
|
||||
}
|
||||
|
||||
std::optional<ushort> Chunk::getNeighborIdx(ushort idx, Face face) {
|
||||
switch (face) {
|
||||
case Face::Forward:
|
||||
|
|
|
@ -4,72 +4,70 @@
|
|||
#include "Voxel.hpp"
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
|
||||
/// Chunk length
|
||||
#define CHUNK_LENGTH 32
|
||||
#define CHUNK_LENGTH2 (CHUNK_LENGTH * CHUNK_LENGTH)
|
||||
#define CHUNK_SIZE (CHUNK_LENGTH2 * CHUNK_LENGTH)
|
||||
|
||||
/// World part as linear 3d voxel array
|
||||
struct Chunk {
|
||||
public:
|
||||
Chunk(const chunk_pos& pos, Generator& rnd);
|
||||
~Chunk();
|
||||
namespace world {
|
||||
using namespace geometry;
|
||||
/// World part as linear 3d voxel array
|
||||
struct Chunk {
|
||||
public:
|
||||
Chunk(const chunk_pos& pos, Generator& rnd);
|
||||
~Chunk();
|
||||
|
||||
/// Update voxels
|
||||
/// @return if modified neightbors to update
|
||||
std::optional<Faces> update();
|
||||
/// Update voxels
|
||||
/// @return if modified neighbors to update
|
||||
std::optional<Faces> update();
|
||||
|
||||
const Voxel* begin() const {
|
||||
return voxels.begin();
|
||||
}
|
||||
inline void invalidate(Faces faces) {
|
||||
upToDate = false;
|
||||
toUpdate = toUpdate | faces;
|
||||
modified = true;
|
||||
}
|
||||
inline const Voxel& get(ushort idx) const {
|
||||
return voxels[idx];
|
||||
}
|
||||
const Voxel& getAt(const chunk_voxel_pos& pos) const {
|
||||
return get(getIdx(pos));
|
||||
}
|
||||
void set(ushort idx, const Voxel& val) {
|
||||
voxels[idx] = val;
|
||||
invalidate(
|
||||
((!getNeighborIdx(idx, Face::Up).has_value()) & Faces::Up) |
|
||||
((!getNeighborIdx(idx, Face::Down).has_value()) & Faces::Down) |
|
||||
((!getNeighborIdx(idx, Face::Left).has_value()) & Faces::Left) |
|
||||
((!getNeighborIdx(idx, Face::Right).has_value()) & Faces::Right) |
|
||||
((!getNeighborIdx(idx, Face::Forward).has_value()) & Faces::Forward) |
|
||||
((!getNeighborIdx(idx, Face::Backward).has_value()) & Faces::Backward));
|
||||
}
|
||||
void setAt(const chunk_voxel_pos& pos, const Voxel& val) {
|
||||
set(getIdx(pos), val);
|
||||
}
|
||||
Item breakAt(const chunk_voxel_pos& pos, const Voxel& val) {
|
||||
const auto idx = getIdx(pos);
|
||||
const auto res = voxels[idx];
|
||||
set(idx, val);
|
||||
return Item{res.Density, res.Material};
|
||||
}
|
||||
// Notify for render
|
||||
inline void invalidate(Faces faces) {
|
||||
upToDate = false;
|
||||
toUpdate = toUpdate | faces;
|
||||
modified = true;
|
||||
}
|
||||
// Get voxel from index
|
||||
inline const Voxel& get(ushort idx) const {
|
||||
return voxels[idx];
|
||||
}
|
||||
// Get voxel from position
|
||||
inline const Voxel& getAt(const chunk_voxel_pos& pos) const {
|
||||
return get(getIdx(pos));
|
||||
}
|
||||
// Set voxel from index
|
||||
void set(ushort idx, const Voxel& val);
|
||||
// Set voxel from position
|
||||
void setAt(const chunk_voxel_pos& pos, const Voxel& val) {
|
||||
set(getIdx(pos), val);
|
||||
}
|
||||
// Break voxel
|
||||
Item breakAt(const chunk_voxel_pos& pos, const Voxel& val) {
|
||||
const auto idx = getIdx(pos);
|
||||
const auto res = voxels[idx];
|
||||
set(idx, val);
|
||||
return Item{res.Density, res.Material};
|
||||
}
|
||||
|
||||
static inline chunk_voxel_pos getPosition(ushort idx) {
|
||||
return chunk_voxel_pos(idx / CHUNK_LENGTH2, (idx / CHUNK_LENGTH) % CHUNK_LENGTH, idx % CHUNK_LENGTH);
|
||||
}
|
||||
static inline ushort getIdx(chunk_voxel_pos pos) {
|
||||
return getIdx(pos.x, pos.y, pos.z);
|
||||
}
|
||||
static inline ushort getIdx(uint x, uint y, uint z) {
|
||||
return (x * CHUNK_LENGTH + y) * CHUNK_LENGTH + z;
|
||||
}
|
||||
static std::optional<ushort> getNeighborIdx(ushort idx, Face dir);
|
||||
static inline chunk_voxel_pos getPosition(ushort idx) {
|
||||
return chunk_voxel_pos(idx / CHUNK_LENGTH2, (idx / CHUNK_LENGTH) % CHUNK_LENGTH, idx % CHUNK_LENGTH);
|
||||
}
|
||||
static inline ushort getIdx(chunk_voxel_pos pos) {
|
||||
return getIdx(pos.x, pos.y, pos.z);
|
||||
}
|
||||
static inline ushort getIdx(uint x, uint y, uint z) {
|
||||
return (x * CHUNK_LENGTH + y) * CHUNK_LENGTH + z;
|
||||
}
|
||||
static std::optional<ushort> getNeighborIdx(ushort idx, Face dir);
|
||||
|
||||
private:
|
||||
/// Chunk data
|
||||
std::array<Voxel, CHUNK_SIZE> voxels;
|
||||
/// Require update
|
||||
bool upToDate = true;
|
||||
/// Neighbors to update
|
||||
Faces toUpdate = Faces::None;
|
||||
/// Modified by player
|
||||
bool modified = false;
|
||||
};
|
||||
private:
|
||||
/// Chunk data
|
||||
std::array<Voxel, CHUNK_SIZE> voxels;
|
||||
/// Require update
|
||||
bool upToDate = true;
|
||||
/// Neighbors to update
|
||||
Faces toUpdate = Faces::None;
|
||||
/// Modified by player
|
||||
bool modified = false;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,33 +4,38 @@
|
|||
#include <tuple>
|
||||
#include "../data/glm.hpp"
|
||||
|
||||
class Generator {
|
||||
public:
|
||||
Generator(int seed = 42) {
|
||||
densityNoise = FastNoiseSIMD::NewFastNoiseSIMD(seed);
|
||||
materialNoise = FastNoiseSIMD::NewFastNoiseSIMD(seed * 5);
|
||||
materialNoise->SetNoiseType(FastNoiseSIMD::Cellular); // NOTE: probably heavy
|
||||
materialNoise->SetCellularReturnType(FastNoiseSIMD::CellValue);
|
||||
materialNoise->SetCellularDistanceFunction(FastNoiseSIMD::Natural);
|
||||
materialNoise->SetFrequency(.1);
|
||||
}
|
||||
~Generator() {
|
||||
delete densityNoise;
|
||||
delete materialNoise;
|
||||
}
|
||||
namespace world {
|
||||
/// Noise generator
|
||||
class Generator {
|
||||
public:
|
||||
Generator(int seed = 42) {
|
||||
densityNoise = FastNoiseSIMD::NewFastNoiseSIMD(seed);
|
||||
materialNoise = FastNoiseSIMD::NewFastNoiseSIMD(seed * 5);
|
||||
materialNoise->SetNoiseType(FastNoiseSIMD::Cellular); // NOTE: probably heavy
|
||||
materialNoise->SetCellularReturnType(FastNoiseSIMD::CellValue);
|
||||
materialNoise->SetCellularDistanceFunction(FastNoiseSIMD::Natural);
|
||||
materialNoise->SetFrequency(.1);
|
||||
}
|
||||
~Generator() {
|
||||
delete densityNoise;
|
||||
delete materialNoise;
|
||||
}
|
||||
|
||||
inline std::pair<float*, float*> getChunk(const chunk_pos& pos, int size) {
|
||||
return {
|
||||
densityNoise->GetNoiseSet(pos.x * size, pos.y * size, pos.z * size, size, size, size),
|
||||
materialNoise->GetNoiseSet(pos.x * size, pos.y * size, pos.z * size, size, size, size),
|
||||
};
|
||||
}
|
||||
inline void freeChunk(std::pair<float*, float*>& set) {
|
||||
FastNoiseSIMD::FreeNoiseSet(set.first);
|
||||
FastNoiseSIMD::FreeNoiseSet(set.second);
|
||||
}
|
||||
/// Get block of given size with index pos.
|
||||
/// @note owning pointers, @see FastNoiseSIMD::FreeNoiseSet
|
||||
inline std::pair<float*, float*> getChunk(const chunk_pos& pos, int size) {
|
||||
return {
|
||||
densityNoise->GetNoiseSet(pos.x * size, pos.y * size, pos.z * size, size, size, size),
|
||||
materialNoise->GetNoiseSet(pos.x * size, pos.y * size, pos.z * size, size, size, size),
|
||||
};
|
||||
}
|
||||
inline void freeChunk(std::pair<float*, float*>& set) {
|
||||
FastNoiseSIMD::FreeNoiseSet(set.first);
|
||||
FastNoiseSIMD::FreeNoiseSet(set.second);
|
||||
}
|
||||
|
||||
private:
|
||||
FastNoiseSIMD *densityNoise;
|
||||
FastNoiseSIMD *materialNoise;
|
||||
};
|
||||
private:
|
||||
FastNoiseSIMD *densityNoise;
|
||||
FastNoiseSIMD *materialNoise;
|
||||
};
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
#include "World.hpp"
|
||||
#include "Universe.hpp"
|
||||
|
||||
#include "../contouring/Dummy.hpp"
|
||||
#include <Remotery.h>
|
||||
|
||||
World::World(const World::options &options): loadPool(2), contouring(std::make_shared<contouring::Dummy>()) {
|
||||
using namespace world;
|
||||
|
||||
Universe::Universe(const Universe::options &options): loadPool(2), contouring(std::make_shared<contouring::Dummy>()) {
|
||||
setOptions(options);
|
||||
}
|
||||
World::~World() {
|
||||
Universe::~Universe() {
|
||||
contouring = NULL;
|
||||
}
|
||||
|
||||
World::LoadPool::LoadPool(size_t count) {
|
||||
Universe::LoadPool::LoadPool(size_t count) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
workers.push_back(std::thread([&] {
|
||||
while (running) {
|
||||
|
@ -24,7 +26,7 @@ World::LoadPool::LoadPool(size_t count) {
|
|||
}));
|
||||
}
|
||||
}
|
||||
World::LoadPool::~LoadPool() {
|
||||
Universe::LoadPool::~LoadPool() {
|
||||
running = false;
|
||||
loadQueue.notify();
|
||||
|
||||
|
@ -33,15 +35,15 @@ World::LoadPool::~LoadPool() {
|
|||
worker.join();
|
||||
}
|
||||
}
|
||||
inline void World::LoadPool::push(const chunk_pos &pos, int weight) { loadQueue.push(pos, weight); }
|
||||
inline bool World::LoadPool::pop(robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> &out) { return loadedQueue.pop(out); }
|
||||
inline size_t World::LoadPool::size() { return loadQueue.size(); }
|
||||
inline void Universe::LoadPool::push(const chunk_pos &pos, int weight) { loadQueue.push(pos, weight); }
|
||||
inline bool Universe::LoadPool::pop(robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> &out) { return loadedQueue.pop(out); }
|
||||
inline size_t Universe::LoadPool::size() { return loadQueue.size(); }
|
||||
|
||||
void World::update(const camera_pos& pos, World::report& rep) {
|
||||
void Universe::update(const camera_pos& pos, Universe::report& rep) {
|
||||
const chunk_pos newPos = glm::divide(pos, chunk_voxel_pos(CHUNK_LENGTH));
|
||||
const auto chunkChange = newPos != last_pos;
|
||||
last_pos = newPos;
|
||||
rmt_ScopedCPUSample(World, 0);
|
||||
rmt_ScopedCPUSample(Universe, 0);
|
||||
|
||||
// Update alive chunks
|
||||
{
|
||||
|
@ -104,17 +106,17 @@ void World::update(const camera_pos& pos, World::report& rep) {
|
|||
}
|
||||
rep.chunk_count.push(chunks.size());
|
||||
}
|
||||
void World::setOptions(const World::options& options) {
|
||||
void Universe::setOptions(const Universe::options& options) {
|
||||
loadDistance = options.loadDistance;
|
||||
keepDistance = options.keepDistance;
|
||||
}
|
||||
|
||||
void World::setContouring(std::shared_ptr<contouring::Abstract> ct) {
|
||||
void Universe::setContouring(std::shared_ptr<contouring::Abstract> ct) {
|
||||
contouring = ct;
|
||||
last_pos = chunk_pos(INT_MAX); // trigger chunkChange on next update
|
||||
}
|
||||
|
||||
std::optional<std::pair<voxel_pos, Voxel>> World::raycast(const Ray &ray) const {
|
||||
std::optional<std::pair<voxel_pos, Voxel>> Universe::raycast(const Ray &ray) const {
|
||||
std::vector<voxel_pos> points;
|
||||
ray.grid(points);
|
||||
std::shared_ptr<Chunk> chunk = NULL;
|
||||
|
@ -136,7 +138,7 @@ std::optional<std::pair<voxel_pos, Voxel>> World::raycast(const Ray &ray) const
|
|||
return {};
|
||||
}
|
||||
|
||||
std::optional<Item> World::set(const voxel_pos& pos, const Voxel& val) {
|
||||
std::optional<Item> Universe::set(const voxel_pos& pos, const Voxel& val) {
|
||||
const auto chunkPos = glm::divide(pos, glm::ivec3(CHUNK_LENGTH));
|
||||
if(const auto& chunk = at(chunkPos)) {
|
||||
return {chunk.value()->breakAt(glm::modulo(pos, glm::ivec3(CHUNK_LENGTH)), val)};
|
||||
|
@ -144,7 +146,7 @@ std::optional<Item> World::set(const voxel_pos& pos, const Voxel& val) {
|
|||
return {};
|
||||
}
|
||||
}
|
||||
ItemList World::setCube(const voxel_pos& pos, const Voxel& val, int radius) {
|
||||
ItemList Universe::setCube(const voxel_pos& pos, const Voxel& val, int radius) {
|
||||
ItemList list;
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
|
@ -0,0 +1,104 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include "../data/unique_queue.hpp"
|
||||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "Chunk.hpp"
|
||||
#include "../data/geometry/Ray.hpp"
|
||||
|
||||
#define REPORT_BUFFER_SIZE 128
|
||||
|
||||
namespace contouring {
|
||||
class Abstract;
|
||||
};
|
||||
|
||||
using namespace data;
|
||||
/// Universe data
|
||||
namespace world {
|
||||
/// Whole universe container
|
||||
class Universe {
|
||||
public:
|
||||
/// Distance management
|
||||
struct options {
|
||||
/// Radius in chunks to load if missing
|
||||
int loadDistance = 5;
|
||||
/// Radius in chunks to keep in memory
|
||||
int keepDistance = 6;
|
||||
};
|
||||
/// Reports to UI
|
||||
struct report {
|
||||
/// Chunks in memory
|
||||
circular_buffer<float> chunk_count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
/// Loaded chunks
|
||||
circular_buffer<float> chunk_load = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
/// Saved chunks
|
||||
circular_buffer<float> chunk_unload = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
};
|
||||
|
||||
Universe(const options&);
|
||||
~Universe();
|
||||
|
||||
/// Update physics and contouring
|
||||
void update(const camera_pos& pos, report& rep);
|
||||
/// Apply new options
|
||||
void setOptions(const options &);
|
||||
|
||||
/// Get nearest voxel colliding ray
|
||||
/// @note ray in world scale
|
||||
std::optional<std::pair<voxel_pos, Voxel>> raycast(const geometry::Ray &ray) const;
|
||||
/// Set voxel at pos
|
||||
std::optional<Item> set(const voxel_pos &pos, const Voxel &val);
|
||||
/// Set cube of voxel with pos as center
|
||||
ItemList setCube(const voxel_pos &pos, const Voxel &val, int radius);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// Data
|
||||
robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> chunks;
|
||||
|
||||
std::optional<std::shared_ptr<Chunk>> at(const chunk_pos& pos) const {
|
||||
const auto it = chunks.find(pos);
|
||||
if(it == chunks.end())
|
||||
return {};
|
||||
return {it->second};
|
||||
}
|
||||
|
||||
/// Generating worker pool
|
||||
class LoadPool {
|
||||
public:
|
||||
LoadPool(size_t size);
|
||||
~LoadPool();
|
||||
|
||||
Generator generator;
|
||||
inline void push(const chunk_pos &pos, int weight);
|
||||
inline bool pop(robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> &out);
|
||||
inline size_t size();
|
||||
|
||||
private:
|
||||
std::vector<std::thread> workers;
|
||||
bool running = true;
|
||||
|
||||
safe_priority_queue<chunk_pos, int> loadQueue;
|
||||
safe_queue<robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>>> loadedQueue;
|
||||
};
|
||||
LoadPool loadPool;
|
||||
unique_queue<chunk_pos> unloadQueue;
|
||||
|
||||
int loadDistance;
|
||||
int keepDistance;
|
||||
|
||||
/// Contouring worker
|
||||
std::shared_ptr<contouring::Abstract> contouring;
|
||||
};
|
||||
}
|
|
@ -2,18 +2,29 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
struct Voxel {
|
||||
unsigned char Density;
|
||||
unsigned short Material;
|
||||
};
|
||||
struct Item {
|
||||
unsigned long long Count;
|
||||
unsigned short Material;
|
||||
};
|
||||
struct ItemList: std::map<unsigned short, unsigned long long> {
|
||||
void add(const std::optional<Item>& item) {
|
||||
if(item) {
|
||||
(*this)[item.value().Material] += item.value().Count;
|
||||
namespace world {
|
||||
/// Universe unit
|
||||
struct Voxel {
|
||||
/// Quantity of material
|
||||
unsigned char Density;
|
||||
/// Material type
|
||||
/// @see world::materials
|
||||
unsigned short Material;
|
||||
};
|
||||
/// Stock of material
|
||||
struct Item {
|
||||
/// Quantity of material
|
||||
unsigned long long Count;
|
||||
/// Material type
|
||||
/// @see world::materials
|
||||
unsigned short Material;
|
||||
};
|
||||
/// List of materials
|
||||
struct ItemList: std::map<unsigned short, unsigned long long> {
|
||||
void add(const std::optional<Item>& item) {
|
||||
if(item) {
|
||||
(*this)[item.value().Material] += item.value().Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include "../data/unique_queue.hpp"
|
||||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "Chunk.hpp"
|
||||
#include "../data/geometry/Ray.hpp"
|
||||
|
||||
#define REPORT_BUFFER_SIZE 128
|
||||
|
||||
namespace contouring {
|
||||
class Abstract;
|
||||
};
|
||||
|
||||
class World {
|
||||
public:
|
||||
struct options {
|
||||
int loadDistance = 5;
|
||||
int keepDistance = 6;
|
||||
};
|
||||
struct report {
|
||||
circular_buffer<float> chunk_count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
circular_buffer<float> chunk_load = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> chunk_unload = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
};
|
||||
|
||||
World(const options&);
|
||||
~World();
|
||||
|
||||
void update(const camera_pos& pos, report& rep);
|
||||
void setOptions(const options &);
|
||||
|
||||
std::optional<std::shared_ptr<Chunk>> at(const chunk_pos& pos) const {
|
||||
const auto it = chunks.find(pos);
|
||||
if(it == chunks.end())
|
||||
return {};
|
||||
return {it->second};
|
||||
}
|
||||
std::optional<std::pair<voxel_pos, Voxel>> raycast(const Ray &ray) const;
|
||||
std::optional<Item> set(const voxel_pos &pos, const Voxel &val);
|
||||
ItemList setCube(const voxel_pos &pos, const Voxel &val, int radius);
|
||||
|
||||
/// 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);
|
||||
|
||||
robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> chunks;
|
||||
|
||||
/// Generating worker pool
|
||||
class LoadPool {
|
||||
public:
|
||||
LoadPool(size_t size);
|
||||
~LoadPool();
|
||||
|
||||
Generator generator;
|
||||
inline void push(const chunk_pos &pos, int weight);
|
||||
inline bool pop(robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> &out);
|
||||
inline size_t size();
|
||||
|
||||
private:
|
||||
std::vector<std::thread> workers;
|
||||
bool running = true;
|
||||
|
||||
safe_priority_queue<chunk_pos, int> loadQueue;
|
||||
safe_queue<robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>>> loadedQueue;
|
||||
};
|
||||
LoadPool loadPool;
|
||||
unique_queue<chunk_pos> unloadQueue;
|
||||
|
||||
int loadDistance;
|
||||
int keepDistance;
|
||||
|
||||
/// Contouring worker
|
||||
std::shared_ptr<contouring::Abstract> contouring;
|
||||
};
|
|
@ -3,8 +3,12 @@
|
|||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace materials {
|
||||
namespace world::materials {
|
||||
/// Materials count
|
||||
static const auto count = 9;
|
||||
/// Materials textures
|
||||
static const std::array<std::string, count> textures = {{"Air", "Sand", "Dirt", "Stone_path", "Mapl", "Seaside_rock", "Stone_wall", "Rough_rock", "Alien"}};
|
||||
/// Materials roughness.
|
||||
/// -1: slope, 0: normal, 1: cube
|
||||
static const std::array<float, count> roughness = {{0, 0, 0, 0, 0, 0, 0, -1, .8}};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue