1
0
Fork 0

Zstd dictionary, forward decl

This commit is contained in:
May B. 2020-07-31 19:09:44 +02:00
parent 8d967cee06
commit 752cd4b1a3
40 changed files with 256 additions and 154 deletions

View File

@ -36,7 +36,7 @@ add_definitions(
-mfma
)
file(GLOB_RECURSE SOURCES "src/*.cpp")
file(GLOB_RECURSE SOURCES "src/*/*.cpp")
file(GLOB INCLUDE_SOURCES "include/imgui-1.76/*.cpp" "include/FastNoiseSIMD/*.cpp" "include/Remotery/lib/*.c")
set(INCLUDE_LIBS
"include/imgui-1.76"
@ -46,7 +46,7 @@ set(INCLUDE_LIBS
"include/robin_hood"
)
add_executable(univerxel ${SOURCES} ${INCLUDE_SOURCES})
add_executable(univerxel "src/main.cpp" ${SOURCES} ${INCLUDE_SOURCES})
target_compile_features(univerxel PUBLIC cxx_std_17)
target_link_libraries(univerxel ${LINKED_LIBS})
target_include_directories(univerxel PRIVATE ${INCLUDE_LIBS})
@ -55,6 +55,7 @@ if(PROFILING)
else(PROFILING)
target_compile_definitions(univerxel PRIVATE RMT_ENABLED=0)
endif(PROFILING)
add_dependencies(univerxel generate_dictionary)
file(COPY content/shaders DESTINATION ${CMAKE_BINARY_DIR}/content)
file(COPY content/textures DESTINATION ${CMAKE_BINARY_DIR}/content)
@ -64,4 +65,17 @@ add_custom_target(docs
COMMAND doxygen ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Build doc."
)
)
# Zstd dictionary
file(GLOB SMP_SOURCES "src/chunk_sampler.cpp" "src/world/Chunk.cpp" "include/FastNoiseSIMD/*.cpp")
add_executable(chunk_sampler EXCLUDE_FROM_ALL ${SMP_SOURCES})
target_compile_features(chunk_sampler PUBLIC cxx_std_17)
target_link_libraries(chunk_sampler ${LINKED_LIBS})
target_include_directories(chunk_sampler PRIVATE "include/FastNoiseSIMD")
add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/content/zstd.dict"
COMMAND "${CMAKE_BINARY_DIR}/chunk_sampler"
COMMAND zstd --train "${CMAKE_BINARY_DIR}/samples/*" -o "${CMAKE_BINARY_DIR}/content/zstd.dict"
DEPENDS chunk_sampler)
add_custom_target(generate_dictionary DEPENDS "${CMAKE_BINARY_DIR}/content/zstd.dict")

View File

@ -11,7 +11,7 @@
- [~] Group files
- [x] Zstd + custom grouping
- [~] Find best region size
- [ ] Zstd Train dictionary
- [x] Zstd Train dictionary
- [~] Low memory: Keep only ifstream
- [ ] Unload unused
- [ ] In memory RLE
@ -28,10 +28,15 @@
- [ ] Leak test
- Valgrind
- Xtree-memory
- [ ] sanitizer
- [ ] clang-tidy
- [ ] cmake
- https://github.com/microsoft/GSL/blob/master/include/gsl/pointers
- [ ] Server
- [ ] ZeroMQ
- [ ] Mutex guard
- [ ] Shared mutex
- [ ] Logger
## Rendering
- [x] Render triangle

32
src/chunk_sampler.cpp Normal file
View File

@ -0,0 +1,32 @@
/**
* \file chunk_sampler.cpp
* \brief Generate uncompressed chunks
* \author Maelys Bois
* \version 0.0.1
*
* Generate random uncompressed chunks for Zstd dictionary training.
*/
#include "world/Chunk.hpp"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <ctime>
#include <filesystem>
/// Entry point
int main(int, char *[])
{
std::srand(std::time(nullptr));
world::Generator generator(std::rand());
std::filesystem::create_directories("samples");
for (size_t i = 0; i < 10000; i++)
{
world::Chunk chunk(chunk_pos(std::rand(), std::rand(), std::rand()), generator);
std::ofstream out("samples/" + std::to_string(i));
chunk.write(out);
out.close();
}
return 0;
}

View File

@ -1,16 +1,11 @@
#pragma once
#include "../data/glm.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>
#include "../world/forward.h"
typedef glm::vec3 camera_pos;
namespace world {
class Chunk;
}
/// Mesh creation
namespace contouring {
/// Generating mesh from world data
@ -24,10 +19,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<world::Chunk>>& data, geometry::Faces neighbors) = 0;
virtual void onUpdate(const chunk_pos &pos, const world::chunk_map& 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<world::Chunk>> &data) = 0;
virtual void onNotify(const chunk_pos &pos, const world::chunk_map &data) = 0;
/// Display ImGui config
virtual void onGui() = 0;
/// Get options

View File

@ -1,6 +1,7 @@
#include "AbstractFlat.hpp"
#include <imgui.h>
#include <toml.h>
#include "../world/Chunk.hpp"
namespace contouring {
@ -42,7 +43,7 @@ namespace contouring {
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(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});
out.emplace_back(glm::translate(scaling, glm::vec3(pos) * glm::vec3(CHUNK_LENGTH)), buffer);
}
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "Abstract.hpp"
#include "../data/math.hpp"
namespace contouring {
/// Generating mesh for chunks 1:1

View File

@ -10,8 +10,8 @@ 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<world::Chunk>> &, geometry::Faces) override {}
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &) override { }
void onUpdate(const chunk_pos &, const world::chunk_map &, geometry::Faces) override {}
void onNotify(const chunk_pos &, const world::chunk_map &) override { }
void onGui() override { }
std::string getOptions() override { return ""; }
void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &, const std::optional<geometry::Frustum>&, float) override { }

View File

@ -4,6 +4,7 @@
#include "../world/materials.hpp"
#include <Remotery.h>
#include <imgui.h>
#include <toml.h>
#include "dualmc.h"
namespace contouring {
@ -13,7 +14,7 @@ namespace contouring {
manifold = opt["manifold"].value_or(manifold);
for (size_t i = 1; i <= 2; i++) {
workers.push_back(std::thread([&] {
workers.emplace_back([&] {
while (running) {
std::pair<chunk_pos, surrounding::corners> ctx;
loadQueue.wait();
@ -21,10 +22,10 @@ namespace contouring {
rmt_ScopedCPUSample(ProcessContouring, 0);
buffer::ShortIndexed::Data data;
render(ctx.second, data);
loadedQueue.push({ctx.first, data});
loadedQueue.emplace(ctx.first, data);
}
}
}));
});
}
}
FlatDualMC::~FlatDualMC() {
@ -48,7 +49,7 @@ namespace contouring {
return ss.str();
}
void FlatDualMC::enqueue(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data) {
void FlatDualMC::enqueue(const chunk_pos &pos, const world::chunk_map &data) {
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
const auto dist2 = glm::length2(pos - center);
if (dist2 <= loadDistance * loadDistance) {
@ -59,7 +60,7 @@ namespace contouring {
}
}
void FlatDualMC::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data, geometry::Faces neighbors) {
void FlatDualMC::onUpdate(const chunk_pos &pos, const world::chunk_map &data, geometry::Faces neighbors) {
enqueue(pos, data);
if (neighbors && (geometry::Faces::Left | geometry::Faces::Down | geometry::Faces::Backward)) {
for (size_t i = 1; i < 8; i++) {
@ -68,7 +69,7 @@ namespace contouring {
}
}
void FlatDualMC::onNotify(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data) {
void FlatDualMC::onNotify(const chunk_pos &pos, const world::chunk_map &data) {
if (buffers.find(pos) == buffers.end()) {
enqueue(pos, data);
}
@ -109,15 +110,14 @@ namespace contouring {
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);
{
grid.reserve(SIZE * SIZE * SIZE);
for (int z = 0; z < SIZE; z++) {
for (int y = 0; y < SIZE; y++) {
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->getAt(chunk_voxel_pos(x % CHUNK_LENGTH, y % CHUNK_LENGTH, z % CHUNK_LENGTH));
grid.push_back({voxel.Density * 1.f / UCHAR_MAX, voxel.Material});
const auto &chunk = surrounding[(z >= CHUNK_LENGTH) + (y >= CHUNK_LENGTH)*2 + (x >= CHUNK_LENGTH)*4];
const auto &voxel = chunk->getAt(chunk_voxel_pos(x % CHUNK_LENGTH, y % CHUNK_LENGTH, z % CHUNK_LENGTH));
grid.emplace_back(voxel.Density * 1.f / UCHAR_MAX, voxel.Material);
}}}
}
{
@ -131,9 +131,9 @@ namespace contouring {
out.materials.reserve(dmc_vertices.size());
out.normals.reserve(dmc_vertices.size());
for (const auto& v: dmc_vertices) {
out.vertices.push_back(glm::vec3(v.x, v.y, v.z));
out.materials.push_back(v.w);
out.normals.push_back(glm::vec3(0));
out.vertices.emplace_back(v.x, v.y, v.z);
out.materials.emplace_back(v.w);
out.normals.emplace_back(0);
}
out.indices.reserve(dmc_tris.size());

View File

@ -26,10 +26,10 @@ namespace contouring {
std::string getOptions() override;
/// Chunk data change
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &, geometry::Faces) override;
void onUpdate(const chunk_pos &, const world::chunk_map &, 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<world::Chunk>> &) override;
void onNotify(const chunk_pos &, const world::chunk_map &) override;
protected:
safe_priority_queue_map<chunk_pos, surrounding::corners, int> loadQueue;
@ -44,7 +44,7 @@ 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<world::Chunk>> &);
void enqueue(const chunk_pos &, const world::chunk_map &);
float iso = .1f;
bool manifold = true;

View File

@ -9,7 +9,7 @@ using namespace geometry;
namespace contouring {
FlatSurroundingBox::FlatSurroundingBox(const std::string &opt) : AbstractFlat(opt) {
for (size_t i = 1; i <= 4; i++) {
workers.push_back(std::thread([&] {
workers.emplace_back([&] {
while (running) {
std::pair<chunk_pos, surrounding::faces> ctx;
loadQueue.wait();
@ -19,11 +19,11 @@ namespace contouring {
render(ctx.second, vertices);
{
rmt_ScopedCPUSample(Index, 0);
loadedQueue.push({ctx.first, buffer::ShortIndexed::Data(vertices)});
loadedQueue.emplace(ctx.first, vertices);
}
}
}
}));
});
}
}
FlatSurroundingBox::~FlatSurroundingBox() {
@ -36,7 +36,7 @@ namespace contouring {
}
}
void FlatSurroundingBox::enqueue(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data) {
void FlatSurroundingBox::enqueue(const chunk_pos &pos, const world::chunk_map &data) {
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
const auto dist2 = glm::length2(pos - center);
if (dist2 <= loadDistance * loadDistance) {
@ -47,7 +47,7 @@ namespace contouring {
}
}
void FlatSurroundingBox::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &data, Faces neighbors) {
void FlatSurroundingBox::onUpdate(const chunk_pos &pos, const world::chunk_map &data, Faces neighbors) {
enqueue(pos, data);
if (neighbors && Faces::Right)
enqueue(pos + g_face_offsets[static_cast<int>(Face::Right)], data);
@ -68,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<world::Chunk>> &data) {
void FlatSurroundingBox::onNotify(const chunk_pos &pos, const world::chunk_map &data) {
if (buffers.find(pos) == buffers.end()) {
enqueue(pos, data);
}

View File

@ -24,10 +24,10 @@ namespace contouring {
void onGui() override;
/// Chunk data change
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &, geometry::Faces) override;
void onUpdate(const chunk_pos &, const world::chunk_map &, 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<world::Chunk>> &) override;
void onNotify(const chunk_pos &, const world::chunk_map &) override;
protected:
safe_priority_queue_map<chunk_pos, surrounding::faces, int> loadQueue;
@ -42,7 +42,7 @@ 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<world::Chunk>> &);
void enqueue(const chunk_pos &, const world::chunk_map &);
private:
static inline bool isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx);

View File

@ -27,7 +27,7 @@ namespace contouring::box {
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(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)]});
out.emplace_back(glm::vec3(g_cube_rotate[static_cast<int>(face)] * glm::vec4(vertex, 1)) * size + position, material, g_cube_normals[static_cast<int>(face)]);
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "Abstract.hpp"
#include <map>
namespace contouring {
static const std::array<std::string, 3> names = {"FlatDualMC", "FlatBox", "Dummy"};

View File

@ -1,10 +1,11 @@
#include "surrounding.hpp"
#include "../world/Chunk.hpp"
#include "../data/math.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<world::Chunk>> &chunks) {
bool load(faces &out, const chunk_pos &chunkPos, const world::chunk_map &chunks) {
{
const auto it = chunks.find(chunkPos);
if (it == chunks.end())
@ -59,7 +60,7 @@ namespace contouring::surrounding {
}
}
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<world::Chunk>> &chunks) {
bool load(corners &out, const chunk_pos &chunkPos, const world::chunk_map &chunks) {
for (size_t i = 0; i < 8; i++) {
const auto it = chunks.find(chunkPos + g_corner_offsets[i]);
if (it == chunks.end())

View File

@ -1,8 +1,7 @@
#pragma once
#include "../data/geometry/Faces.hpp"
#include <memory>
#include <robin_hood.h>
#include "../world/forward.h"
namespace world {
class Chunk;
@ -11,7 +10,7 @@ namespace contouring::surrounding {
const auto CENTER = 6;
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<world::Chunk>> &chunks);
bool load(faces &out, const chunk_pos &chunkPos, const world::chunk_map &chunks);
std::pair<ushort, ushort> getNeighborIdx(ushort idx, geometry::Face face);
@ -27,5 +26,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<world::Chunk>> &chunks);
bool load(corners &out, const chunk_pos &chunkPos, const world::chunk_map &chunks);
}

View File

@ -7,6 +7,7 @@
#include "../data/glm.hpp"
#include "../data/geometry/Frustum.hpp"
#include "../data/geometry/Ray.hpp"
typedef glm::vec3 camera_pos;
/// Moving perspective camera
class Camera {
@ -37,10 +38,10 @@ public:
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; }
camera_pos getPosition() const { return Position; }
float getDepth() const { return o.far; }
constexpr glm::mat4 getViewMatrix() const { return ViewMatrix; }
constexpr glm::mat4 getProjectionMatrix() const { return ProjectionMatrix; }
constexpr camera_pos getPosition() const { return Position; }
constexpr float getDepth() const { return o.far; }
private:
GLFWwindow *window;

View File

@ -19,12 +19,12 @@ namespace geometry {
/// 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;
inline void grid(std::vector<glm::lvec3>& points) const {
glm::lvec3 current = from + glm::vec3(.5f);
const glm::lvec3 d = dir * dist;
const glm::lvec3 inc = glm::lvec3((d.x < 0) ? -1 : 1, (d.y < 0) ? -1 : 1, (d.z < 0) ? -1 : 1);
const glm::lvec3 size = glm::abs(d);
const glm::lvec3 delta = size << 1ll;
if ((size.x >= size.y) && (size.x >= size.z)) {
int err_1 = delta.y - size.x;

View File

@ -20,7 +20,7 @@ struct SphereIterator {
out.reserve(out.size() + dxz * dxz);
for (int z = minz; z <= maxz; z++) {
for (int x = minx; x <= maxx; x++) {
out.push_back(glm::ivec3(x, y, z));
out.emplace_back(x, y, z);
}}
}
}

View File

@ -1,44 +1,10 @@
#pragma once
#include <glm/glm.hpp>
#include <glm/gtx/hash.hpp>
namespace glm {
typedef vec<3, long long> lvec3;
typedef vec<4, long long> lvec4;
typedef vec<3, ushort> usvec3;
typedef vec<3, unsigned char> ucvec3;
} // namespace glm
typedef glm::vec3 camera_pos;
typedef glm::lvec3 voxel_pos;
typedef glm::ivec3 chunk_pos;
typedef glm::ucvec3 chunk_voxel_pos;
typedef glm::ivec3 region_pos;
typedef glm::ucvec3 region_chunk_pos;
namespace glm {
ivec3 inline iround(const vec3& p) {
return ivec3(std::round<int>(p.x), std::round<int>(p.y), std::round<int>(p.z));
}
int inline length2(const ivec3& a) {
return a.x * a.x + a.y * a.y + a.z * a.z;
}
ivec3 inline diff(const ivec3& a, const ivec3& b) {
return glm::abs(glm::abs(a) - glm::abs(b));
}
uint inline rem(long long value, uint m) {
return value < 0 ? ((value+1) % (long long)m) + m - 1 : value % (long long)m;
}
int inline div(long long value, uint m) {
return value < 0 ? ((value+1) / (long long)m) - 1 : value / (long long)m;
}
chunk_voxel_pos inline modulo(const voxel_pos& value, const chunk_voxel_pos& m) {
return chunk_voxel_pos(rem(value.x, m.x), rem(value.y, m.y), rem(value.z, m.z));
}
chunk_pos inline divide(const voxel_pos &value, const chunk_voxel_pos &m)
{
return chunk_pos(div(value.x, m.x), div(value.y, m.y), div(value.z, m.z));
}
}

32
src/data/math.hpp Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include "glm.hpp"
#include <glm/gtx/hash.hpp>
namespace glm {
constexpr ivec3 inline iround(const vec3& p) {
return ivec3(std::round<int>(p.x), std::round<int>(p.y), std::round<int>(p.z));
}
constexpr int inline length2(const ivec3& a) {
return a.x * a.x + a.y * a.y + a.z * a.z;
}
constexpr ivec3 inline diff(const ivec3& a, const ivec3& b) {
return glm::abs(glm::abs(a) - glm::abs(b));
}
constexpr uint inline rem(long long value, uint m) {
return value < 0 ? ((value+1) % (long long)m) + m - 1 : value % (long long)m;
}
constexpr int inline div(long long value, uint m) {
return value < 0 ? ((value+1) / (long long)m) - 1 : value / (long long)m;
}
constexpr ucvec3 inline modulo(const lvec3& value, const ucvec3& m) {
return ucvec3(rem(value.x, m.x), rem(value.y, m.y), rem(value.z, m.z));
}
constexpr ivec3 inline divide(const lvec3 &value, const ucvec3 &m) {
return ivec3(div(value.x, m.x), div(value.y, m.y), div(value.z, m.z));
}
constexpr std::pair<ivec3, ucvec3> inline split(const lvec3 &value, const ucvec3 &m) {
return {divide(value, m), modulo(value, m)};
}
}

View File

@ -25,7 +25,7 @@ namespace data {
public:
void push(const K& key, const V& val, const W& weight) {
std::unique_lock<std::mutex> lock(mutex);
heap.push_back({key, weight});
heap.emplace_back(key, weight);
std::push_heap(heap.begin(), heap.end(), cmpByWeight);
map.insert_or_assign(key, val);
cv.notify_one();
@ -87,7 +87,7 @@ namespace data {
public:
void push(const K& key, const W& weight) {
std::unique_lock<std::mutex> lock(mutex);
heap.push_back({key, weight});
heap.emplace_back(key, weight);
std::push_heap(heap.begin(), heap.end(), cmpByWeight);
set.insert(key);
cv.notify_one();

View File

@ -21,6 +21,13 @@ namespace data {
cv.notify_one();
}
template <typename... _Args>
void emplace(_Args &&... __args) {
std::unique_lock<std::mutex> lock(mutex);
queue.emplace(std::forward<_Args>(__args)...);
cv.notify_one();
}
bool pop(T& out) {
std::unique_lock<std::mutex> lock(mutex);
if (queue.empty())

View File

@ -7,22 +7,18 @@
* Univerxel main program.
*/
#include <stdexcept>
#include <iostream>
#include <chrono>
#include <thread>
#include "render/window.hpp"
#include "render/UI.hpp"
#include "control/InputMap.hpp"
#include "control/Camera.hpp"
#include "control/InputMap.hpp" //TODO: add options
#include "render/Renderer.hpp"
#include "render/pass/ColorProgram.hpp"
#include "render/buffer/Colored.hpp"
#include "world/Universe.hpp"
#include "state.h"
#include "data/math.hpp"
#include <Remotery.h>

View File

@ -49,7 +49,7 @@ void Renderer::unloadTextures() {
void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD) {
std::vector<std::string> terrainTextures;
for(const auto texture: world::materials::textures) {
terrainTextures.push_back(texturePath + "/terrain/" + texture);
terrainTextures.emplace_back(texturePath + "/terrain/" + texture);
}
TextureAtlas = pass::Program::loadTextureArray(terrainTextures, "", mipMapLOD);
NormalAtlas = pass::Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD);

View File

@ -1,10 +1,9 @@
#pragma once
#include <GL/glew.h>
#include <imgui.h>
#include "pass/Context.hpp"
#include "pass/MainProgram.hpp"
#include "pass/SkyProgram.hpp"
#include "pass/Context.hpp"
class Camera;
/// Handle rendering passes and params
@ -23,7 +22,7 @@ public:
/// Textures quality
float mipMapLOD = -.5;
/// Depth color
ImVec4 clear_color;
glm::vec4 clear_color;
};
Renderer(const options&);

View File

@ -1,8 +1,9 @@
#include "UI.hpp"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include "pass/Program.hpp"
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include "../state.h"
#include "../contouring/Abstract.hpp"
#include "../world/materials.hpp"
@ -88,7 +89,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
actions = actions | Actions::RendererSharders;
}
}
if (ImGui::ColorEdit3("Fog color", (float *)&options.renderer.clear_color)) {
if (ImGui::ColorEdit3("Fog color", &options.renderer.clear_color[0])) {
actions = actions | Actions::ClearColor;
}
if (ImGui::Checkbox("Wireframe", &options.renderer.wireframe))

View File

@ -1,10 +1,11 @@
#pragma once
#include "imgui.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "../state.h"
class options;
class state;
class reports;
namespace UI {
/// Retro actions to state
enum class Actions {

View File

@ -7,6 +7,8 @@
namespace buffer {
/// Vertex properties
struct VertexData {
VertexData(const glm::vec3 &position, GLushort material, const glm::vec3 &normal):
Position(position), Material(material), Normal(normal) { }
glm::vec3 Position;
GLushort Material;
glm::vec3 Normal;

View File

@ -8,13 +8,13 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
std::vector<std::string> flags;
if(opts.pbr)
flags.push_back("PBR");
flags.emplace_back("PBR");
if(opts.triplanar)
flags.push_back("TRIPLANAR");
flags.emplace_back("TRIPLANAR");
if (opts.fog)
flags.push_back("FOG");
flags.emplace_back("FOG");
if (opts.blend)
flags.push_back("BLEND");
flags.emplace_back("BLEND");
std::vector<Shader*> shaders;
shaders.push_back(loadShader(GL_VERTEX_SHADER, flags));

View File

@ -1,6 +1,5 @@
#include "Shader.hpp"
#include <cassert>
#include <iostream>
#include <fstream>
#include <sstream>

View File

@ -16,14 +16,14 @@
#include "control/Camera.hpp"
#include "contouring/index.hpp"
inline ImColor fromHex(const std::string& str) {
inline glm::vec4 fromHex(const std::string& str) {
int rgb[3] = {UCHAR_MAX};
sscanf(str.c_str() + 1, "%02X%02X%02X", (unsigned int *)&rgb[0], (unsigned int *)&rgb[1], (unsigned int *)&rgb[2]);
return ImColor(rgb[0], rgb[1], rgb[2]);
return glm::vec4(rgb[0] * 1.f / UCHAR_MAX, rgb[1] * 1.f / UCHAR_MAX, rgb[2] * 1.f / UCHAR_MAX, 1);
}
inline std::string toHexa(const ImVec4& rgba) {
inline std::string toHexa(const glm::vec4& rgb) {
auto out = (char*)malloc(8 * sizeof(char));
sprintf(out, "#%02X%02X%02X", (int)(rgba.x * UCHAR_MAX), (int)(rgba.y * UCHAR_MAX), (int)(rgba.z * UCHAR_MAX));
sprintf(out, "#%02X%02X%02X", (int)(rgb.x * UCHAR_MAX), (int)(rgb.y * UCHAR_MAX), (int)(rgb.z * UCHAR_MAX));
return std::string(out);
}

View File

@ -1,7 +1,7 @@
#include "Chunk.hpp"
#include <FastNoiseSIMD.h>
#include "materials.hpp"
#include <algorithm>
using namespace world;
@ -35,7 +35,7 @@ Chunk::Chunk(std::istream& str) {
i++;
}
}
assert(i == CHUNK_SIZE-1);
assert(("Mismatch data length", i == CHUNK_SIZE-1));
#else
for(auto& voxel: voxels) {
str.read(reinterpret_cast<char *>(&voxel.Density), sizeof(Voxel::Density));

View File

@ -6,7 +6,6 @@
#include <sstream>
/// Chunk length
#define CHUNK_LENGTH 32
#define CHUNK_LENGTH2 (CHUNK_LENGTH * CHUNK_LENGTH)
#define CHUNK_SIZE (CHUNK_LENGTH2 * CHUNK_LENGTH)

View File

@ -2,7 +2,7 @@
#include <FastNoiseSIMD.h>
#include <tuple>
#include "../data/glm.hpp"
#include "position.h"
namespace world {
/// Noise generator

View File

@ -63,7 +63,7 @@ void Region::load() {
const auto saved = content.insert({pos, data}).second;
#endif
if(!saved) {
std::cout << "Duplicated chunk: " << path << ":" << pos.x << "." << pos.y << "." << pos.z << std::endl;
std::cout << "Duplicated chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << std::endl;
}
file.peek();
}
@ -78,7 +78,7 @@ void Region::load() {
file.close();
#endif
}
bool Region::read(const region_chunk_pos& pos, ZSTD_DCtx* dctx, data& out) {
bool Region::read(const region_chunk_pos& pos, ZSTD_DCtx* ctx, ZSTD_DDict *dict, data& out) {
#ifdef LOW_MEMORY
std::unique_lock lock(mutex);
@ -102,22 +102,24 @@ bool Region::read(const region_chunk_pos& pos, ZSTD_DCtx* dctx, data& out) {
const auto maxSize = ZSTD_getFrameContentSize(in->data(), in->size());
out.resize(maxSize);
const auto actualSize = ZSTD_decompressDCtx(dctx, out.data(), out.size(), in->data(), in->size());
const auto actualSize = ZSTD_decompress_usingDDict(ctx, out.data(), out.size(), in->data(), in->size(), dict);
if(ZSTD_isError(actualSize)) {
std::cout << "Corrupted region chunk: " << path << ":" << pos.x << "." << pos.y << "." << pos.z << std::endl;
std::cout << "Corrupted region chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
<< ZSTD_getErrorName(actualSize) << std::endl;
return false;
}
out.resize(actualSize);
return true;
}
void Region::save(const region_chunk_pos& pos, ZSTD_CCtx* cctx, const std::string_view& in) {
void Region::save(const region_chunk_pos& pos, ZSTD_CCtx* ctx, ZSTD_CDict* dict, const std::string_view& in) {
const auto maxSize = ZSTD_compressBound(in.size());
const auto buffer = new Region::data();
buffer->resize(maxSize);
const auto actualSize = ZSTD_compressCCtx(cctx, buffer->data(), buffer->capacity(), in.data(), in.size(), ZSTD_CLEVEL_DEFAULT);
const auto actualSize = ZSTD_compress_usingCDict(ctx, buffer->data(), buffer->capacity(), in.data(), in.size(), dict);
if (ZSTD_isError(actualSize)) {
std::cout << "Corrupted chunk save: " << path << ":" << pos.x << "." << pos.y << "." << pos.z << std::endl;
std::cout << "Corrupted chunk save: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
<< ZSTD_getErrorName(actualSize) << std::endl;
return;
}
buffer->resize(actualSize);

View File

@ -1,13 +1,13 @@
#pragma once
#include "../data/glm.hpp"
#include <vector>
#include <string>
#include <shared_mutex>
#include <zstd.h>
#include <robin_hood.h>
#include <fstream>
#include <zstd.h>
#include "forward.h"
#include "../data/math.hpp"
#define REGION_LENGTH 32
namespace world {
///Group of chunks saved as a single file
class Region {
@ -17,8 +17,8 @@ namespace world {
typedef std::vector<char> data;
bool read(const region_chunk_pos &pos, ZSTD_DCtx *dctx, data &out);
void save(const region_chunk_pos &pos, ZSTD_CCtx *cctx, const std::string_view &in);
bool read(const region_chunk_pos &pos, ZSTD_DCtx *dctx, ZSTD_DDict *ddict, data &out);
void save(const region_chunk_pos &pos, ZSTD_CCtx *cctx, ZSTD_CDict *cdict, const std::string_view &in);
private:
std::string path;

View File

@ -1,11 +1,10 @@
#include "Universe.hpp"
#include "../contouring/Dummy.hpp"
#include "../data/geometry/Sphere.hpp"
#include <Remotery.h>
#include <filesystem>
#include <fstream>
#include <zstd.h>
#include "../contouring/Dummy.hpp"
#include "Chunk.hpp"
using namespace world;
@ -20,9 +19,24 @@ Universe::Universe(const Universe::options &options): generator(42), contouring(
running = true;
std::filesystem::create_directories(folderPath);
{ // Load dictionary
std::ifstream is("content/zstd.dict", std::ios::in | std::ios::binary | std::ios::ate);
if(!is.good()) {
std::cout << "missing dict" << std::endl;
exit(1);
}
const auto end = is.tellg();
is.seekg(0, std::ios::beg);
std::vector<char> dict(end - is.tellg());
is.read(dict.data(), dict.size());
is.close();
cdict = ZSTD_createCDict(dict.data(), dict.size(), ZSTD_CLEVEL_DEFAULT);
ddict = ZSTD_createDDict(dict.data(), dict.size());
}
// Load workers
for (size_t i = 0; i < 4; i++) {
loadWorkers.push_back(std::thread([&] {
loadWorkers.emplace_back([&] {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
while (running) {
chunk_pos ctx;
@ -34,7 +48,7 @@ Universe::Universe(const Universe::options &options): generator(42), contouring(
const region_chunk_pos cPos = glm::modulo(ctx, region_chunk_pos(REGION_LENGTH));
const auto reg = getRegion(rPos);
Region::data data;
if(reg->read(cPos, dctx, data)) {
if(reg->read(cPos, dctx, ddict, data)) {
rmt_ScopedCPUSample(ProcessRead, 0);
vec_istream idata(data);
std::istream iss(&idata);
@ -46,12 +60,12 @@ Universe::Universe(const Universe::options &options): generator(42), contouring(
}
}
ZSTD_freeDCtx(dctx);
}));
});
}
// Save workers
for (size_t i = 0; i < 2; i++) {
saveWorkers.push_back(std::thread([&] {
saveWorkers.emplace_back([&] {
ZSTD_CCtx* cctx = ZSTD_createCCtx();
while (running) {
robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> ctx;
@ -64,11 +78,11 @@ Universe::Universe(const Universe::options &options): generator(42), contouring(
const region_pos rPos = glm::divide(ctx.first, region_chunk_pos(REGION_LENGTH));
const region_chunk_pos cPos = glm::modulo(ctx.first, region_chunk_pos(REGION_LENGTH));
const auto reg = getRegion(rPos);
reg->save(cPos, cctx, out.str());
reg->save(cPos, cctx, cdict, out.str());
}
}
ZSTD_freeCCtx(cctx);
}));
});
}
}
Universe::~Universe() {
@ -97,6 +111,9 @@ Universe::~Universe() {
if (worker.joinable())
worker.join();
}
ZSTD_freeCDict(cdict);
ZSTD_freeDDict(ddict);
}
std::shared_ptr<Region> Universe::getRegion(const region_pos& pos) {
@ -171,6 +188,7 @@ void Universe::update(const camera_pos& pos, Universe::report& rep) {
}
}
rep.chunk_count.push(chunks.size());
rep.region_count.push(regionCache.size());
}
void Universe::setOptions(const Universe::options& options) {
loadDistance = options.loadDistance;

View File

@ -1,15 +1,19 @@
#pragma once
#include <string>
#include <memory>
#include <thread>
#include <string>
#include <shared_mutex>
#include "../data/math.hpp"
#include "../data/safe_queue.hpp"
#include "../data/safe_priority_queue.hpp"
#include "../data/circular_buffer.hpp"
#include "Chunk.hpp"
#include "Region.hpp"
#include "../data/geometry/Ray.hpp"
#include <shared_mutex>
#include "forward.h"
#include "Voxel.hpp"
#include "Region.hpp"
#include "Generator.hpp"
typedef glm::vec3 camera_pos;
#define REPORT_BUFFER_SIZE 128
@ -40,9 +44,11 @@ namespace world {
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);
/// Regions in memory
circular_buffer<float> region_count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
};
Universe(const options&);
Universe(const options &);
~Universe();
/// Update physics and contouring
@ -69,7 +75,7 @@ namespace world {
chunk_pos last_pos = chunk_pos(INT_MAX);
/// Data
robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> chunks;
chunk_map chunks;
std::optional<std::shared_ptr<Chunk>> at(const chunk_pos& pos) const {
const auto it = chunks.find(pos);
@ -94,6 +100,8 @@ namespace world {
std::shared_mutex regionMutex; //MAYBE: shared_guard
robin_hood::unordered_map<region_pos, std::shared_ptr<Region>> regionCache;
ZSTD_CDict *cdict;
ZSTD_DDict *ddict;
//TODO: region pick list
std::shared_ptr<Region> getRegion(const region_pos &);

10
src/world/forward.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <robin_hood.h>
#include "position.h"
namespace world {
class Chunk;
class Region;
typedef robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> chunk_map;
}

12
src/world/position.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include "../data/glm.hpp"
#define CHUNK_LENGTH 32
#define REGION_LENGTH 32
typedef glm::lvec3 voxel_pos;
typedef glm::ivec3 chunk_pos;
typedef glm::ucvec3 chunk_voxel_pos;
typedef glm::ivec3 region_pos;
typedef glm::ucvec3 region_chunk_pos;