Compare commits
2 Commits
7920e8b473
...
71a52bd7e3
Author | SHA1 | Date |
---|---|---|
May B. | 71a52bd7e3 | |
May B. | 686505bded |
12
TODO.md
12
TODO.md
|
@ -14,6 +14,7 @@
|
|||
- [~] Authentication
|
||||
- [x] Compression
|
||||
- [ ] Encryption
|
||||
- DTLS
|
||||
- [x] Embedded
|
||||
- [x] Standalone
|
||||
|
||||
|
@ -24,13 +25,19 @@
|
|||
- [ ] Local prediction
|
||||
- [ ] Contouring service
|
||||
- [~] Edit
|
||||
- [ ] Shape iterators
|
||||
- Cube
|
||||
- Sphere
|
||||
- [ ] More types
|
||||
- Anchor
|
||||
- Prevent suffocation
|
||||
- [ ] Local prediction
|
||||
- [~] Occlusion Culling
|
||||
- [ ] Iterator ray
|
||||
- [ ] Cast from chunk center
|
||||
- [x] Transparency
|
||||
- [ ] Entities
|
||||
- [~] Entities
|
||||
- Get models
|
||||
|
||||
## Hello universe
|
||||
|
||||
|
@ -63,6 +70,7 @@
|
|||
|
||||
## Hello darkness
|
||||
|
||||
- [ ] Break area part to entity
|
||||
- [ ] Slash screen
|
||||
- [ ] Start/Pause menu
|
||||
- [ ] QUIC protocal
|
||||
|
@ -70,7 +78,7 @@
|
|||
- [ ] Octree
|
||||
- [ ] Better Lod
|
||||
- [ ] VK
|
||||
- [ ] Pipeline recreate
|
||||
- [ ] Instanced draw
|
||||
- [ ] Pipeline cache
|
||||
- [ ] Reuse descriptors
|
||||
- [ ] Secondary buffers
|
||||
|
|
|
@ -6,5 +6,5 @@ layout(location = 0) out vec4 color;
|
|||
in vec4 Color;
|
||||
|
||||
void main(){
|
||||
color = vec4(Color.xyz, .5);
|
||||
color = Color;
|
||||
}
|
BIN
resource/content/shaders/Color.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Color.fs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -2,14 +2,14 @@
|
|||
|
||||
|
||||
layout(location = 0) in vec3 Position_modelspace;
|
||||
layout(location = 1) in vec4 Color_model;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform vec4 Col;
|
||||
|
||||
out vec4 Color;
|
||||
|
||||
void main(){
|
||||
gl_Position = MVP * vec4(Position_modelspace, 1);
|
||||
Color = Color_model;
|
||||
Color = Col;
|
||||
}
|
||||
|
||||
|
|
BIN
resource/content/shaders/Color.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Color.vs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -122,7 +122,7 @@ void main() {
|
|||
|
||||
vec3 blendWeights = abs(vs.FaceNormal_modelspace);
|
||||
blendWeights = blendWeights - plateauSize;
|
||||
blendWeights = pow(max(blendWeights, 0), vec3(transitionSpeed));
|
||||
blendWeights = normalize(pow(max(blendWeights, 0), vec3(transitionSpeed)));
|
||||
vec2 UVx = vs.Position_modelspace.yz * texScale;
|
||||
vec2 UVy = vs.Position_modelspace.zx * texScale;
|
||||
vec2 UVz = vs.Position_modelspace.xy * texScale;
|
||||
|
|
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.geo.ins.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.geo.ins.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.ins.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.ins.fs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -6,5 +6,5 @@ layout(location = 0) in vec4 Color;
|
|||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main(){
|
||||
color = vec4(Color.xyz, .5);
|
||||
color = Color;
|
||||
}
|
|
@ -6,15 +6,15 @@ layout(binding = 0) uniform UniformBufferObject {
|
|||
} UBO;
|
||||
layout(push_constant) uniform PushConst {
|
||||
mat4 model;
|
||||
vec4 color;
|
||||
} Push;
|
||||
|
||||
layout(location = 0) in vec3 Position_modelspace;
|
||||
layout(location = 1) in vec4 Color_model;
|
||||
|
||||
layout(location = 0) out vec4 Color;
|
||||
|
||||
void main(){
|
||||
gl_Position = UBO.proj * UBO.view * Push.model * vec4(Position_modelspace, 1);
|
||||
Color = Color_model;
|
||||
Color = Push.color;
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ if(TRIPLANAR) {
|
|||
vec2 UVy = vs.Position_modelspace.zx * texScale;
|
||||
vec2 UVz = vs.Position_modelspace.xy * texScale;
|
||||
|
||||
tex = getTriTexture(TextureAtlas, UVx, UVy, UVz, blendWeights);
|
||||
tex = getTriTexture(TextureAtlas, UVx, UVy, UVz, normalize(blendWeights));
|
||||
|
||||
if(PBR) {
|
||||
// Whiteout normal blend
|
||||
|
|
|
@ -66,6 +66,8 @@ void Client::run(server_handle* const localHandle) {
|
|||
const auto ray_result = world->raycast(camera.getRay() * options.voxel_density);
|
||||
if(auto target = std::get_if<world::Universe::ray_target>(&ray_result)) {
|
||||
state.look_at = *target;
|
||||
const auto &tool = options.editor.tool;
|
||||
state.can_fill = true; //FIXME: world->canFill(target->pos, tool.shape, tool.radius);
|
||||
} else {
|
||||
state.look_at = {};
|
||||
}
|
||||
|
@ -75,11 +77,11 @@ void Client::run(server_handle* const localHandle) {
|
|||
ZoneScopedN("Edit");
|
||||
const auto &tool = options.editor.tool;
|
||||
if (inputs.isPressing(Mouse::Left))
|
||||
world->emit(world::action::FillCube(
|
||||
state.look_at.value().pos, world::Voxel(world::materials::AIR, tool.emptyAir * world::Voxel::DENSITY_MAX), tool.radius));
|
||||
world->emit(world::action::FillShape(
|
||||
state.look_at.value().pos, world::Voxel(world::materials::AIR, tool.emptyAir * world::Voxel::DENSITY_MAX), tool.shape, tool.radius));
|
||||
else if (inputs.isPressing(Mouse::Right))
|
||||
world->emit(world::action::FillCube(
|
||||
state.look_at.value().pos, world::Voxel(tool.material, world::Voxel::DENSITY_MAX), tool.radius));
|
||||
world->emit(world::action::FillShape(
|
||||
state.look_at.value().pos, world::Voxel(tool.material, world::Voxel::DENSITY_MAX), tool.shape, tool.radius));
|
||||
}
|
||||
if (inputs.isDown(Input::Throw)) {
|
||||
//FIXME: register entity type world->addEntity(entity_id(0), {state.position * options.voxel_density, glm::vec3(10, 0, 0)});
|
||||
|
@ -183,18 +185,20 @@ void Client::run(server_handle* const localHandle) {
|
|||
}
|
||||
{ // Entities
|
||||
const auto pass = pipeline->beginEntityPass();
|
||||
/*const auto draw = [&](const std::vector<glm::mat4>& models, buffer::Abstract *const buffer) {
|
||||
reports.models_count += models.size();
|
||||
reports.tris_count += buffer->draw(pass(models));
|
||||
};*/
|
||||
//world->getEntitiesModels(draw, frustum, offset, options.voxel_density);
|
||||
const auto draw = [&](size_t idx, const std::vector<glm::mat4> &models) {
|
||||
if(const auto buffer = state.contouring->getEntityModel(idx)) {
|
||||
reports.models_count += models.size();
|
||||
reports.tris_count += pass(buffer, models);
|
||||
}
|
||||
};
|
||||
world->getEntitiesModels(draw, frustum, offset, options.voxel_density);
|
||||
}
|
||||
{
|
||||
const auto pass = pipeline->beginIndicatorPass();
|
||||
if(state.look_at.has_value()) { // Indicator
|
||||
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().pos.second + state.look_at.value().offset - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.editor.tool.radius)), glm::vec3(1 + options.editor.tool.radius * 2));
|
||||
reports.models_count++;
|
||||
reports.tris_count += pass(model);
|
||||
reports.tris_count += pass(model, options.editor.tool.shape, state.can_fill ? glm::vec4(1, 1, 1, .5) : glm::vec4(1, 0, 0, .5));
|
||||
}
|
||||
}
|
||||
pipeline->postProcess();
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
}
|
||||
|
||||
editor.visible = config["editor"]["visible"].value_or(editor.visible);
|
||||
editor.tool.shape = static_cast<world::action::Shape>(config["editor"]["tool"]["shape"].value_or(static_cast<int>(editor.tool.shape)));
|
||||
editor.tool.radius = config["editor"]["tool"]["radius"].value_or(editor.tool.radius);
|
||||
editor.tool.material = config["editor"]["tool"]["material"].value_or(editor.tool.material);
|
||||
editor.tool.emptyAir = config["editor"]["tool"]["empty_air"].value_or(editor.tool.emptyAir);
|
||||
|
@ -156,6 +157,7 @@ public:
|
|||
config.insert_or_assign("editor", toml::table({
|
||||
{"visible", editor.visible},
|
||||
{"tool", toml::table({
|
||||
{"shape", static_cast<int>(editor.tool.shape)},
|
||||
{"radius", editor.tool.radius},
|
||||
{"material", editor.tool.material},
|
||||
{"empty_air", editor.tool.emptyAir}
|
||||
|
@ -205,6 +207,7 @@ public:
|
|||
struct {
|
||||
bool visible = false;
|
||||
struct {
|
||||
world::action::Shape shape = world::action::Shape::Cube;
|
||||
int radius = 2;
|
||||
unsigned short material = 5;
|
||||
bool emptyAir = true;
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
#include "../../core/geometry/Frustum.hpp"
|
||||
#include "../../core/geometry/Ray.hpp"
|
||||
#include "../../core/geometry/Faces.hpp"
|
||||
#include "../../core/flags.hpp"
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
namespace render { class LodModel; }
|
||||
namespace render {
|
||||
class Model;
|
||||
class LodModel;
|
||||
}
|
||||
/// Mesh creation (from world to render)
|
||||
namespace contouring {
|
||||
/// Generating mesh from world data
|
||||
|
@ -43,5 +48,19 @@ namespace contouring {
|
|||
/// Get buffers hitting occlusion rays with model matrices
|
||||
/// @note buffers invalidated after update
|
||||
virtual void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) = 0;
|
||||
|
||||
/// Get buffer corresponding to entity idx
|
||||
virtual render::Model* getEntityModel(size_t) = 0;
|
||||
/// Get entity instance model if in frustum
|
||||
static _FORCE_INLINE_ bool CullEntity(glm::mat4& out, const glm::vec3& size, const glm::vec3& scale, const glm::ifvec3& pos,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density)
|
||||
{
|
||||
const glm::vec3 fPos = (glm::vec3(pos.raw_as_long() - offset * glm::llvec3(density)) + pos.offset) / glm::vec3(density);
|
||||
if (!frustum.has_value() || frustum.value().contains(geometry::Box::fromMin(fPos, size))) {
|
||||
out = glm::scale(glm::translate(glm::mat4(1), fPos * (float)density), scale);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -60,6 +60,22 @@ namespace contouring {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
{ //TODO: render for chunk(s)
|
||||
auto pack = [](const glm::vec3 &pos) {
|
||||
return render::PackedVertexData(meshopt_quantizeHalf(pos.x), meshopt_quantizeHalf(pos.y),
|
||||
meshopt_quantizeHalf(pos.z), world::materials::textures_map[7],
|
||||
meshopt_quantizeHalf(pos.x), meshopt_quantizeHalf(pos.y),
|
||||
meshopt_quantizeHalf(pos.z));
|
||||
};
|
||||
playerModel = render::Model::Create(render::Model::Data({
|
||||
pack({1, 0, 0}), pack({0, 1, 0}), pack({0, 0, 1}),
|
||||
pack({-1, 0, 0}), pack({0, -1, 0}), pack({0, 0, -1})
|
||||
}, {
|
||||
0, 1, 2, 0, 5, 1, 0, 2, 4, 0, 4, 5,
|
||||
1, 3, 2, 5, 3, 1, 2, 3, 4, 4, 3, 5
|
||||
}));
|
||||
}
|
||||
}
|
||||
FlatDualMC::~FlatDualMC() {
|
||||
running = false;
|
||||
|
@ -361,4 +377,8 @@ namespace contouring {
|
|||
}
|
||||
}
|
||||
|
||||
render::Model* FlatDualMC::getEntityModel(size_t) {
|
||||
return playerModel.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,10 +38,14 @@ namespace contouring {
|
|||
/// @note buffers invalidated after update
|
||||
void getModels(draw_call draw, const glm::ifvec3 &from, float far, const std::vector<glm::vec3> &occlusion, const glm::llvec3 &offset, int density, bool solid) override;
|
||||
|
||||
render::Model* getEntityModel(size_t) override;
|
||||
|
||||
protected:
|
||||
//FIXME: use unique_ptr
|
||||
robin_hood::unordered_map<area_id, robin_hood::pair<area_info, robin_hood::unordered_map<chunk_pos, std::pair<render::LodModel *, render::LodModel *>>>> buffers;
|
||||
|
||||
std::unique_ptr<render::Model> playerModel;
|
||||
|
||||
safe_priority_queue_map<area_<chunk_pos>, surrounding::corners, int, area_hash> loadQueue;
|
||||
safe_queue<std::pair<area_<chunk_pos>, std::pair<render::LodModel::LodData, render::LodModel::LodData>>> loadedQueue;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../core/flags.hpp"
|
||||
#include "../../core/world/actions.hpp"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -73,8 +74,8 @@ public:
|
|||
virtual std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass(bool solid) = 0;
|
||||
/// Get started entity program
|
||||
virtual std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() = 0;
|
||||
/// Draw cube indicator
|
||||
virtual std::function<size_t(glm::mat4)> beginIndicatorPass() = 0;
|
||||
/// Draw line indicator (model, shape, color)
|
||||
virtual std::function<size_t(glm::mat4, world::action::Shape, glm::vec4)> beginIndicatorPass() = 0;
|
||||
/// Apply postprocessing
|
||||
virtual void postProcess() = 0;
|
||||
/// Finalise frame
|
||||
|
|
|
@ -227,6 +227,7 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
|
|||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SliderInt("Radius", &options.editor.tool.radius, 0, 10);
|
||||
ImGui::Combo("Shape", (int*)&options.editor.tool.shape, world::action::SHAPES);
|
||||
ImGui::Checkbox("Empty air", &options.editor.tool.emptyAir);
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Is cleaned area breathable");
|
||||
|
|
|
@ -15,10 +15,27 @@ const std::vector<glm::vec3> Shape::SKY_CUBE = {
|
|||
{-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
|
||||
{-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}
|
||||
};
|
||||
const std::pair<std::vector<glm::vec3>, std::vector<glm::vec4>> Indicator::CUBE = {{
|
||||
const std::vector<glm::vec3> Shape::LINE_CUBE = {
|
||||
{0, 0, 0}, {0, 0, 1}, {0, 0, 1}, {0, 1, 1}, {0, 1, 1}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 1}, {1, 0, 1}, {1, 1, 1},
|
||||
{1, 1, 1}, {1, 1, 0}, {1, 1, 0}, {1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {1, 1, 1}, {0, 1, 0}, {1, 1, 0}
|
||||
}, {
|
||||
};
|
||||
constexpr auto SINPIOVER4 = 0.853553391f;
|
||||
const std::vector<glm::vec3> Shape::LINE_SPHERE = {
|
||||
{1, .5f, .5f}, {SINPIOVER4, SINPIOVER4, .5f}, {SINPIOVER4, SINPIOVER4, .5f}, {.5f, 1, .5f},
|
||||
{.5f, 1, .5f}, {1-SINPIOVER4, SINPIOVER4, .5f}, {1-SINPIOVER4, SINPIOVER4, .5f}, {0, .5f, .5f},
|
||||
{1, .5f, .5f}, {SINPIOVER4, 1-SINPIOVER4, .5f}, {SINPIOVER4, 1-SINPIOVER4, .5f}, {.5f, 0, .5f},
|
||||
{.5f, 0, .5f}, {1-SINPIOVER4, 1-SINPIOVER4, .5f}, {1-SINPIOVER4, 1-SINPIOVER4, .5f}, {0, .5f, .5f},
|
||||
{1, .5f, .5f}, {SINPIOVER4, .5f, SINPIOVER4}, {SINPIOVER4, .5f, SINPIOVER4}, {.5f, .5f, 1},
|
||||
{.5f, .5f, 1}, {1-SINPIOVER4, .5f, SINPIOVER4}, {1-SINPIOVER4, .5f, SINPIOVER4}, {0, .5f, .5f},
|
||||
{1, .5f, .5f}, {SINPIOVER4, .5f, 1-SINPIOVER4}, {SINPIOVER4, .5f, 1-SINPIOVER4}, {.5f, .5f, 0},
|
||||
{.5f, .5f, 0}, {1-SINPIOVER4, .5f, 1-SINPIOVER4}, {1-SINPIOVER4, .5f, 1-SINPIOVER4}, {0, .5f, .5f},
|
||||
{.5f, 1, .5f}, {.5f, SINPIOVER4, SINPIOVER4}, {.5f, SINPIOVER4, SINPIOVER4}, {.5f, .5f, 1},
|
||||
{.5f, .5f, 1}, {.5f, 1-SINPIOVER4, SINPIOVER4}, {.5f, 1-SINPIOVER4, SINPIOVER4}, {.5f, 0, .5f},
|
||||
{.5f, 1, .5f}, {.5f, SINPIOVER4, 1-SINPIOVER4}, {.5f, SINPIOVER4, 1-SINPIOVER4}, {.5f, .5f, 0},
|
||||
{.5f, .5f, 0}, {.5f, 1-SINPIOVER4, 1-SINPIOVER4}, {.5f, 1-SINPIOVER4, 1-SINPIOVER4}, {.5f, 0, .5f}
|
||||
};
|
||||
const std::pair<std::vector<glm::vec3>, std::vector<glm::vec4>> ColoredShape::LINE_CUBE = {Shape::LINE_CUBE,
|
||||
{
|
||||
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1},
|
||||
{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
|
||||
}};
|
||||
|
|
|
@ -45,14 +45,16 @@ public:
|
|||
virtual ~Shape() { }
|
||||
|
||||
static const std::vector<glm::vec3> SKY_CUBE;
|
||||
static const std::vector<glm::vec3> LINE_CUBE;
|
||||
static const std::vector<glm::vec3> LINE_SPHERE;
|
||||
};
|
||||
|
||||
/// Color lines model
|
||||
class Indicator {
|
||||
class ColoredShape {
|
||||
public:
|
||||
virtual ~Indicator() { }
|
||||
virtual ~ColoredShape() { }
|
||||
|
||||
static const std::pair<std::vector<glm::vec3>, std::vector<glm::vec4>> CUBE;
|
||||
static const std::pair<std::vector<glm::vec3>, std::vector<glm::vec4>> LINE_CUBE;
|
||||
};
|
||||
|
||||
/// VertexData model with index
|
||||
|
|
|
@ -18,7 +18,8 @@ constexpr auto GL_MINOR = 6;
|
|||
#define TEXTURES_DIR CONTENT_DIR "textures/"
|
||||
|
||||
Renderer::Renderer(const renderOptions& options):
|
||||
IndicatorCubeBuffer(Indicator::CUBE.first, Indicator::CUBE.second) {
|
||||
IndicatorCubeBuffer(Shape::LINE_CUBE), IndicatorSphereBuffer(Shape::LINE_SPHERE)
|
||||
{
|
||||
glGenVertexArrays(1, &VertexArrayID);
|
||||
glBindVertexArray(VertexArrayID);
|
||||
|
||||
|
@ -87,6 +88,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, const windowOption
|
|||
|
||||
sInstance = new Renderer(opt);
|
||||
sInstance->setVSync(windOpt.targetFPS < Window::MIN_FPS);
|
||||
Model::MakeDefault();
|
||||
LodModel::MakeDefault();
|
||||
return true;
|
||||
}
|
||||
|
@ -121,11 +123,12 @@ std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> Rend
|
|||
};
|
||||
}
|
||||
|
||||
std::function<size_t(glm::mat4)> Renderer::beginIndicatorPass() {
|
||||
std::function<size_t(glm::mat4, world::action::Shape, glm::vec4)> Renderer::beginIndicatorPass() {
|
||||
IndicatorPass->useIt();
|
||||
return [&](glm::mat4 model) {
|
||||
IndicatorPass->setup(this, model);
|
||||
return IndicatorCubeBuffer.draw();
|
||||
return [&](glm::mat4 model, world::action::Shape shape, glm::vec4 color) {
|
||||
IndicatorPass->setup(this, model, color);
|
||||
return shape == world::action::Shape::Cube ?
|
||||
IndicatorCubeBuffer.draw(GL_LINES) : IndicatorSphereBuffer.draw(GL_LINES);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
void beginFrame() override;
|
||||
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass(bool solid) override;
|
||||
std::function<size_t(render::Model *const, const std::vector<glm::mat4>&)> beginEntityPass() override;
|
||||
std::function<size_t(glm::mat4)> beginIndicatorPass() override;
|
||||
std::function<size_t(glm::mat4, world::action::Shape, glm::vec4)> beginIndicatorPass() override;
|
||||
void postProcess() override;
|
||||
void endFrame() override;
|
||||
void swapBuffer(Window&) override;
|
||||
|
@ -72,7 +72,8 @@ private:
|
|||
std::unique_ptr<pass::EntityProgram> EntityPass;
|
||||
std::unique_ptr<pass::SkyProgram> SkyPass;
|
||||
std::unique_ptr<pass::ColorProgram> IndicatorPass;
|
||||
Indicator IndicatorCubeBuffer;
|
||||
Shape IndicatorCubeBuffer;
|
||||
Shape IndicatorSphereBuffer;
|
||||
|
||||
glm::mat4 ProjectionMatrix;
|
||||
glm::mat4 ViewMatrix;
|
||||
|
|
|
@ -11,16 +11,16 @@ Shape::Shape(const std::vector<glm::vec3>& pos) {
|
|||
Shape::~Shape() {
|
||||
glDeleteBuffers(1, &bufferId);
|
||||
}
|
||||
size_t Shape::draw() {
|
||||
size_t Shape::draw(GLenum format) {
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
|
||||
glDrawArrays(GL_TRIANGLES, 0, size);
|
||||
glDrawArrays(format, 0, size);
|
||||
glDisableVertexAttribArray(0);
|
||||
return size;
|
||||
}
|
||||
|
||||
Indicator::Indicator(const std::vector<glm::vec3>& pos, const std::vector<glm::vec4>& col) {
|
||||
ColoredShape::ColoredShape(const std::vector<glm::vec3>& pos, const std::vector<glm::vec4>& col) {
|
||||
assert(pos.size() == col.size());
|
||||
size = pos.size();
|
||||
glGenBuffers(1, &vertexBufferId);
|
||||
|
@ -30,11 +30,11 @@ Indicator::Indicator(const std::vector<glm::vec3>& pos, const std::vector<glm::v
|
|||
glBindBuffer(GL_ARRAY_BUFFER, colorBufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, col.size() * sizeof(glm::vec4), col.data(), GL_STATIC_DRAW);
|
||||
}
|
||||
Indicator::~Indicator() {
|
||||
ColoredShape::~ColoredShape() {
|
||||
glDeleteBuffers(1, &colorBufferId);
|
||||
glDeleteBuffers(1, &vertexBufferId);
|
||||
}
|
||||
void Indicator::enableAttribs() {
|
||||
void ColoredShape::enableAttribs() {
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
|
||||
|
@ -43,17 +43,17 @@ void Indicator::enableAttribs() {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, colorBufferId);
|
||||
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void *)0);
|
||||
}
|
||||
void Indicator::disableAttribs() {
|
||||
void ColoredShape::disableAttribs() {
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
size_t Indicator::draw() {
|
||||
size_t ColoredShape::draw() {
|
||||
enableAttribs();
|
||||
glDrawArrays(GL_LINES, 0, size);
|
||||
disableAttribs();
|
||||
return size;
|
||||
}
|
||||
size_t Indicator::drawInstanced(size_t count) {
|
||||
size_t ColoredShape::drawInstanced(size_t count) {
|
||||
enableAttribs();
|
||||
glDrawArraysInstanced(GL_LINES, 0, size, count);
|
||||
disableAttribs();
|
||||
|
@ -144,6 +144,13 @@ size_t LodModel::drawInstanced(size_t i) {
|
|||
return i * count;
|
||||
}
|
||||
|
||||
std::unique_ptr<render::Model> createModel(const Model::Data& data) {
|
||||
return std::make_unique<Model>(data);
|
||||
}
|
||||
void Model::MakeDefault() {
|
||||
createFunc = createModel;
|
||||
}
|
||||
|
||||
std::unique_ptr<render::LodModel> createLodModel(const LodModel::LodData& data) {
|
||||
return std::make_unique<LodModel>(data);
|
||||
}
|
||||
|
|
|
@ -13,17 +13,17 @@ public:
|
|||
Shape(const std::vector<glm::vec3>&);
|
||||
~Shape();
|
||||
|
||||
size_t draw();
|
||||
size_t draw(GLenum format);
|
||||
|
||||
private:
|
||||
size_t size;
|
||||
GLuint bufferId;
|
||||
};
|
||||
|
||||
class Indicator final: public render::Indicator {
|
||||
class ColoredShape final: public render::ColoredShape {
|
||||
public:
|
||||
Indicator(const std::vector<glm::vec3>&, const std::vector<glm::vec4>&);
|
||||
~Indicator();
|
||||
ColoredShape(const std::vector<glm::vec3>&, const std::vector<glm::vec4>&);
|
||||
~ColoredShape();
|
||||
|
||||
size_t draw();
|
||||
size_t drawInstanced(size_t count);
|
||||
|
@ -42,6 +42,8 @@ public:
|
|||
Model(const Data&);
|
||||
~Model();
|
||||
|
||||
static void MakeDefault();
|
||||
|
||||
size_t draw();
|
||||
size_t drawInstanced(size_t count);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ ColorProgram::ColorProgram(): Program() {
|
|||
load(shaders);
|
||||
|
||||
MVPMatrixID = glGetUniformLocation(ProgramID, "MVP");
|
||||
ColID = glGetUniformLocation(ProgramID, "Col");
|
||||
}
|
||||
|
||||
ColorProgram::~ColorProgram() { }
|
||||
|
@ -20,11 +21,15 @@ ColorProgram::~ColorProgram() { }
|
|||
std::string ColorProgram::getName() const {
|
||||
return "Color";
|
||||
}
|
||||
void ColorProgram::setup(render::gl::Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
void ColorProgram::setup(render::gl::Renderer *renderer, glm::mat4 modelMatrix, glm::vec4 color) {
|
||||
const auto mvp = renderer->getProjectionMatrix() * renderer->getViewMatrix() * modelMatrix;
|
||||
setMVP(&mvp[0][0]);
|
||||
setCol(&color[0]);
|
||||
}
|
||||
|
||||
void ColorProgram::setMVP(const GLfloat *matrix) {
|
||||
glUniformMatrix4fv(MVPMatrixID, 1, GL_FALSE, matrix);
|
||||
}
|
||||
void ColorProgram::setCol(const GLfloat *color) {
|
||||
glUniform4fv(ColID, 1, color);
|
||||
}
|
||||
|
|
|
@ -9,13 +9,15 @@ namespace pass {
|
|||
ColorProgram();
|
||||
~ColorProgram();
|
||||
|
||||
void setup(render::gl::Renderer *, glm::mat4 modelMatrix);
|
||||
void setup(render::gl::Renderer *, glm::mat4 modelMatrix, glm::vec4 color);
|
||||
|
||||
protected:
|
||||
std::string getName() const override;
|
||||
void setMVP(const GLfloat *matrix);
|
||||
void setCol(const GLfloat *color);
|
||||
|
||||
private:
|
||||
GLuint MVPMatrixID;
|
||||
GLuint ColID;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ void SkyProgram::start(render::gl::Renderer *renderer) {
|
|||
void SkyProgram::draw(render::gl::Renderer *renderer) {
|
||||
useIt();
|
||||
start(renderer);
|
||||
CubeBuffer.draw();
|
||||
CubeBuffer.draw(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
void SkyProgram::setView(const GLfloat *matrix) {
|
||||
|
|
|
@ -23,8 +23,9 @@ CommandCenter::CommandCenter(VkDevice device, const PhysicalDeviceInfo &info, co
|
|||
}
|
||||
}
|
||||
|
||||
indicCubeBuffer = Indicator::Create(Indicator::CUBE.first, Indicator::CUBE.second);
|
||||
if (!indicCubeBuffer) {
|
||||
indicSphereBuffer = Shape::Create(Shape::LINE_SPHERE);
|
||||
indicCubeBuffer = Shape::Create(Shape::LINE_CUBE);
|
||||
if (!(indicCubeBuffer && indicSphereBuffer)) {
|
||||
FATAL("Failed to create vertex buffer!");
|
||||
}
|
||||
|
||||
|
@ -315,21 +316,37 @@ size_t CommandCenter::recordModel(uint32_t i, const Subpass &worldPass, const Un
|
|||
vkCmdDrawIndexed(graphicsBuffers[i], size, 1, modelBuffer->getIndexStart(), 0, 0);
|
||||
return size;
|
||||
}
|
||||
void CommandCenter::startEntityPass(uint32_t) { }
|
||||
void CommandCenter::startEntityPass(uint32_t, const Subpass&) { }
|
||||
size_t CommandCenter::recordModels(uint32_t i, const Subpass &entityPass, const std::vector<glm::mat4> &matrices, const Model *const modelBuffer) {
|
||||
VkBuffer vertexBuffers[] = {modelBuffer->getVertex()};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets);
|
||||
vkCmdBindIndexBuffer(graphicsBuffers[i], modelBuffer->getIndex(), 0, VK_INDEX_TYPE_UINT16);
|
||||
|
||||
auto size = modelBuffer->getIndexSize();
|
||||
UniqueCurvaturePush push;
|
||||
push.curvature = 0;
|
||||
for(const auto& matrix: matrices) {
|
||||
push.model = matrix;
|
||||
vkCmdPushConstants(graphicsBuffers[i], entityPass.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push), &push);
|
||||
vkCmdDrawIndexed(graphicsBuffers[i], size, 1, 0, 0, 0);
|
||||
}
|
||||
return size * matrices.size();
|
||||
}
|
||||
void CommandCenter::startIndicPass(uint32_t idx, const Subpass& indicPass) {
|
||||
vkCmdNextSubpass(graphicsBuffers[idx], VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(graphicsBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, indicPass.pipeline);
|
||||
vkCmdBindDescriptorSets(graphicsBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, indicPass.layout, 0, 1, &indicDescriptorSets[idx], 0, nullptr);
|
||||
}
|
||||
size_t CommandCenter::recordIndicator(uint32_t idx, const Subpass& indicPass, glm::mat4 model) {
|
||||
ModelPush push{model};
|
||||
size_t CommandCenter::recordIndicator(uint32_t idx, const Subpass& indicPass, const ModelColorPush& push, bool isCube) {
|
||||
vkCmdPushConstants(graphicsBuffers[idx], indicPass.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push), &push);
|
||||
|
||||
VkBuffer vertexBuffers[] = {indicCubeBuffer->getRef()};
|
||||
const auto buffer = isCube ? indicCubeBuffer.get() : indicSphereBuffer.get();
|
||||
VkBuffer vertexBuffers[] = {buffer->getRef()};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(graphicsBuffers[idx], 0, 1, vertexBuffers, offsets);
|
||||
vkCmdDraw(graphicsBuffers[idx], indicCubeBuffer->size, 1, 0, 0);
|
||||
return indicCubeBuffer->size;
|
||||
vkCmdDraw(graphicsBuffers[idx], buffer->size, 1, 0, 0);
|
||||
return buffer->size;
|
||||
}
|
||||
void CommandCenter::recordPostprocess(uint32_t idx, const Subpass& skyPass, bool skybox) {
|
||||
vkCmdNextSubpass(graphicsBuffers[idx], VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
|
|
@ -26,9 +26,10 @@ public:
|
|||
void startRecording(uint32_t idx, VkRenderPass, VkExtent2D, const VoxelUBO&);
|
||||
void startWorldPass(uint32_t idx, const Subpass&);
|
||||
size_t recordModel(uint32_t idx, const Subpass &worldPass, const UniqueCurvaturePush&, const LodModel *const);
|
||||
void startEntityPass(uint32_t idx);
|
||||
void startEntityPass(uint32_t idx, const Subpass &entityPass);
|
||||
size_t recordModels(uint32_t idx, const Subpass &entityPass, const std::vector<glm::mat4>&, const Model *const);
|
||||
void startIndicPass(uint32_t idx, const Subpass&);
|
||||
size_t recordIndicator(uint32_t idx, const Subpass&, glm::mat4 model);
|
||||
size_t recordIndicator(uint32_t idx, const Subpass&, const ModelColorPush&, bool isCube);
|
||||
void recordPostprocess(uint32_t idx, const Subpass&, bool skybox);
|
||||
void recordUI(uint32_t idx, VkRenderPass uiPass, VkExtent2D, const std::function<void(VkCommandBuffer)> &);
|
||||
void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence);
|
||||
|
@ -65,7 +66,8 @@ private:
|
|||
std::unique_ptr<TextureArray> voxelHOSAtlas;
|
||||
|
||||
std::vector<VkDescriptorSet> indicDescriptorSets;
|
||||
std::unique_ptr<Indicator> indicCubeBuffer;
|
||||
std::unique_ptr<Shape> indicCubeBuffer;
|
||||
std::unique_ptr<Shape> indicSphereBuffer;
|
||||
|
||||
std::vector<VkDescriptorSet> skyDescriptorSets;
|
||||
std::unique_ptr<TextureCube> skyboxTexture;
|
||||
|
|
|
@ -464,7 +464,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
{ // Indicator pipeline
|
||||
VkPushConstantRange pushRange{};
|
||||
pushRange.offset = 0;
|
||||
pushRange.size = sizeof(ModelPush);
|
||||
pushRange.size = sizeof(ModelColorPush);
|
||||
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
setLayout(indicPass, {indicDescriptorSet}, {pushRange});
|
||||
auto shaderStages = setShaders(indicPass, "Color");
|
||||
|
@ -476,12 +476,12 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
auto bindingDescription = Indicator::getBindingDescription();
|
||||
auto bindingDescription = Shape::getBindingDescription();
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||
auto attributeDescriptions = Indicator::getAttributeDescription();
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size();
|
||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||
auto attributeDescription = Shape::getAttributeDescription();
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = 1;
|
||||
vertexInputInfo.pVertexAttributeDescriptions = &attributeDescription;
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
// Voxels (world & entity) passes descriptor set
|
||||
constexpr VkDescriptorSetLayout getVoxelDescriptorSet() const { return voxelDescriptorSet; }
|
||||
constexpr const Subpass& getWorldPass() const { return worldPass; }
|
||||
constexpr const Subpass &getEntitiesPass() const { return worldPass; }
|
||||
constexpr VkDescriptorSetLayout getIndicDescriptorSet() const { return indicDescriptorSet; }
|
||||
constexpr const Subpass &getIndicPass() const { return indicPass; }
|
||||
constexpr VkDescriptorSetLayout getSkyDescriptorSet() const { return skyDescriptorSet; }
|
||||
|
|
|
@ -415,6 +415,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, const windowOption
|
|||
}
|
||||
|
||||
sInstance = new Renderer(instance, device, physicalInfo, opt);
|
||||
Model::MakeDefault();
|
||||
LodModel::MakeDefault();
|
||||
return true;
|
||||
}
|
||||
|
@ -471,19 +472,26 @@ std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> Rend
|
|||
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> Renderer::beginEntityPass() {
|
||||
assert(currentImage < swapChain->getImageViews().size());
|
||||
|
||||
commandCenter->startEntityPass(currentImage);
|
||||
return [&](render::Model *const, const std::vector<glm::mat4>&) {
|
||||
return 0; //EntityPass->setup(this, models);
|
||||
auto& pass = pipeline->getEntitiesPass();
|
||||
commandCenter->startEntityPass(currentImage, pass);
|
||||
return [&](render::Model *const rBuffer, const std::vector<glm::mat4>& models) {
|
||||
auto buffer = dynamic_cast<render::vk::Model *const>(rBuffer);
|
||||
buffer->setLastUse(currentImage);
|
||||
return commandCenter->recordModels(currentImage, pass, models, buffer);
|
||||
};
|
||||
return [](render::Model *const, const std::vector<glm::mat4> &) { return 0; };
|
||||
}
|
||||
|
||||
std::function<size_t(glm::mat4)> Renderer::beginIndicatorPass() {
|
||||
std::function<size_t(glm::mat4, world::action::Shape, glm::vec4)> Renderer::beginIndicatorPass() {
|
||||
assert(currentImage < swapChain->getImageViews().size());
|
||||
|
||||
auto &pass = pipeline->getIndicPass();
|
||||
commandCenter->startIndicPass(currentImage, pass);
|
||||
return [&](glm::mat4 model) {
|
||||
return commandCenter->recordIndicator(currentImage, pass, model);
|
||||
return [&](glm::mat4 model, world::action::Shape shape, glm::vec4 color) {
|
||||
ModelColorPush push{};
|
||||
push.model = model;
|
||||
push.color = color;
|
||||
return commandCenter->recordIndicator(currentImage, pass, push, shape == world::action::Shape::Cube);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
void beginFrame() override;
|
||||
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass(bool solid) override;
|
||||
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() override;
|
||||
std::function<size_t(glm::mat4)> beginIndicatorPass() override;
|
||||
std::function<size_t(glm::mat4, world::action::Shape, glm::vec4)> beginIndicatorPass() override;
|
||||
void postProcess() override;
|
||||
void recordUI(std::function<void(VkCommandBuffer)>);
|
||||
void endFrame() override;
|
||||
|
|
|
@ -9,7 +9,7 @@ std::unique_ptr<Shape> Shape::Create(const std::vector<glm::vec3>& vertices) {
|
|||
return std::unique_ptr<Shape>(new Shape(tmp.ref, std::move(mem), vertices.size()));
|
||||
}
|
||||
|
||||
std::unique_ptr<Indicator> Indicator::Create(const std::vector<glm::vec3>& vert, const std::vector<glm::vec4>& cols) {
|
||||
std::unique_ptr<ColoredShape> ColoredShape::Create(const std::vector<glm::vec3>& vert, const std::vector<glm::vec4>& cols) {
|
||||
assert(vert.size() == cols.size());
|
||||
std::vector<Vertex> vertices;
|
||||
vertices.reserve(vert.size());
|
||||
|
@ -20,7 +20,7 @@ std::unique_ptr<Indicator> Indicator::Create(const std::vector<glm::vec3>& vert,
|
|||
vk::Buffer::info tmp;
|
||||
data_view view(vertices);
|
||||
auto mem = createBuffer(view.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, view, tmp);
|
||||
return std::unique_ptr<Indicator>(new Indicator(vertices.size(), tmp.ref, std::move(mem)));
|
||||
return std::unique_ptr<ColoredShape>(new ColoredShape(vertices.size(), tmp.ref, std::move(mem)));
|
||||
}
|
||||
|
||||
std::unique_ptr<Model> Model::Create(const Data& data) {
|
||||
|
@ -38,6 +38,13 @@ std::unique_ptr<LodModel> LodModel::Create(const LodData& data) {
|
|||
return std::unique_ptr<LodModel>(new LodModel(data.first.indices.size(), data.second, tmp.at(0).ref, tmp.at(1).ref, std::move(mem)));
|
||||
}
|
||||
|
||||
std::unique_ptr<render::Model> createModelVk(const Model::Data& data) {
|
||||
return Model::Create(data);
|
||||
}
|
||||
void Model::MakeDefault() {
|
||||
render::Model::createFunc = createModelVk;
|
||||
}
|
||||
|
||||
std::unique_ptr<render::LodModel> createLodModelVk(const LodModel::LodData& data) {
|
||||
return LodModel::Create(data);
|
||||
}
|
||||
|
|
|
@ -33,11 +33,11 @@ protected:
|
|||
Buffer(ref, std::move(mem)), size(size) { }
|
||||
};
|
||||
|
||||
class Indicator final: public render::Indicator, public Buffer {
|
||||
class ColoredShape final: public render::ColoredShape, public Buffer {
|
||||
public:
|
||||
const size_t size;
|
||||
|
||||
static std::unique_ptr<Indicator> Create(const std::vector<glm::vec3>&, const std::vector<glm::vec4>&);
|
||||
static std::unique_ptr<ColoredShape> Create(const std::vector<glm::vec3>&, const std::vector<glm::vec4>&);
|
||||
|
||||
struct Vertex {
|
||||
alignas(16) glm::vec3 pos;
|
||||
|
@ -65,14 +65,18 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
Indicator(size_t size, VkBuffer ref, memory::ptr mem): Buffer(ref, std::move(mem)), size(size) {}
|
||||
ColoredShape(size_t size, VkBuffer ref, memory::ptr mem): Buffer(ref, std::move(mem)), size(size) {}
|
||||
|
||||
};
|
||||
|
||||
class Model final: public render::Model, public ShortIndexedVertexBuffer {
|
||||
public:
|
||||
constexpr size_t getIndexSize() const { return indexSize; }
|
||||
|
||||
static std::unique_ptr<Model> Create(const Data &);
|
||||
|
||||
static void MakeDefault();
|
||||
|
||||
static VkVertexInputBindingDescription getBindingDescription() {
|
||||
VkVertexInputBindingDescription description{};
|
||||
description.binding = 0;
|
||||
|
@ -158,6 +162,10 @@ struct VoxelUBO {
|
|||
struct ModelPush {
|
||||
alignas(16) glm::mat4 model;
|
||||
};
|
||||
struct ModelColorPush {
|
||||
alignas(16) glm::mat4 model;
|
||||
alignas(16) glm::vec4 color;
|
||||
};
|
||||
struct CurvaturePush {
|
||||
alignas(16) glm::vec4 sphereProj;
|
||||
alignas(4) float curvature;
|
||||
|
|
|
@ -9,6 +9,7 @@ struct state {
|
|||
bool capture_mouse = true;
|
||||
camera_pos position = camera_pos(voxel_pos(0), 1);
|
||||
std::optional<world::Universe::ray_target> look_at = {};
|
||||
bool can_fill = true;
|
||||
|
||||
contouring::Abstract* contouring;
|
||||
|
||||
|
|
|
@ -97,8 +97,9 @@ void DistantUniverse::pullNetwork(voxel_pos pos) {
|
|||
}
|
||||
|
||||
case server_packet_type::TELEPORT: {
|
||||
PacketReader(packet).read(pos);
|
||||
onTeleport(pos);
|
||||
auto reader = PacketReader(packet);
|
||||
if (reader.read(playerId) && reader.read(pos))
|
||||
onTeleport(pos);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -199,6 +200,45 @@ void DistantUniverse::pullNetwork(voxel_pos pos) {
|
|||
break;
|
||||
}
|
||||
|
||||
case server_packet_type::ENTITY_TYPES: {
|
||||
entities.clear();
|
||||
auto reader = PacketReader(packet, true);
|
||||
while(!reader.isFull()) {
|
||||
size_t index;
|
||||
glm::vec3 size;
|
||||
glm::vec3 scale;
|
||||
if(reader.read(index) && reader.read(size) && reader.read(scale)) {
|
||||
entities.set_emplace(index, size, scale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case server_packet_type::ENTITIES: {
|
||||
auto reader = PacketReader(packet, true);
|
||||
while(!reader.isFull()) {
|
||||
size_t entity_idx;
|
||||
size_t count;
|
||||
if (!(reader.read(entity_idx) && reader.read(count)))
|
||||
break;
|
||||
|
||||
if (auto entity = entities.get(entity_idx)) {
|
||||
entity->instances.clear();
|
||||
for (size_t i = 0; i < count && !reader.isFull(); i++) {
|
||||
size_t idx;
|
||||
glm::ifvec3 pos;
|
||||
glm::vec3 vel;
|
||||
if (reader.read(idx) && reader.read(pos) && reader.read(vel))
|
||||
entity->instances.set_emplace(idx, Universe::Entity::Instance{pos, vel});
|
||||
}
|
||||
} else {
|
||||
LOG_W("Unknown entity type " << entity_idx);
|
||||
reader.skip(count * (sizeof(size_t) + sizeof(glm::ifvec3) + sizeof(glm::vec3)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_W("Bad packet from server");
|
||||
break;
|
||||
|
@ -218,8 +258,8 @@ void DistantUniverse::emit(const action::packet &action) {
|
|||
peer.send(net::client_packet_type::MOVE, move->pos, net::channel_type::NOTIFY);
|
||||
} else if(const auto message = std::get_if<action::Message>(&action)) {
|
||||
peer.send(net::client_packet_type::MESSAGE, message->text.data(), message->text.size(), net::channel_type::RELIABLE);
|
||||
} else if(const auto fillCube = std::get_if<action::FillCube>(&action)) {
|
||||
peer.send(net::client_packet_type::FILL_CUBE, *fillCube, net::channel_type::RELIABLE);
|
||||
} else if(const auto fill = std::get_if<action::FillShape>(&action)) {
|
||||
peer.send(net::client_packet_type::FILL_SHAPE, *fill, net::channel_type::RELIABLE);
|
||||
} else {
|
||||
LOG_W("Bad action " << action.index());
|
||||
}
|
||||
|
@ -227,4 +267,24 @@ void DistantUniverse::emit(const action::packet &action) {
|
|||
|
||||
Universe::ray_result DistantUniverse::raycast(const geometry::Ray &ray) const {
|
||||
return Raycast(ray, areas);
|
||||
}
|
||||
|
||||
void DistantUniverse::getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>& call,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density)
|
||||
{
|
||||
std::vector<glm::mat4> mats;
|
||||
entities.iter([&](size_t eId, const Entity &entity) {
|
||||
entity.instances.iter([&](size_t iId, const Universe::Entity::Instance &inst) {
|
||||
if (eId == PLAYER_ENTITY_ID.index && iId == playerId)
|
||||
return;
|
||||
|
||||
glm::mat4 tmp;
|
||||
if (contouring::Abstract::CullEntity(tmp, entity.size, entity.scale, inst.pos, frustum, offset, density))
|
||||
mats.push_back(tmp);
|
||||
});
|
||||
if(!mats.empty()) {
|
||||
call(eId, mats);
|
||||
mats.resize(0);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -18,14 +18,30 @@ namespace world::client {
|
|||
|
||||
ray_result raycast(const geometry::Ray &) const override;
|
||||
|
||||
void getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>&,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density) override;
|
||||
|
||||
bool isDisconnected() const override { return peer.isDisconnected(); }
|
||||
|
||||
size_t getPlayerId() const override { return playerId; }
|
||||
|
||||
protected:
|
||||
void pullNetwork(voxel_pos);
|
||||
|
||||
/// Alive areas containing chunks
|
||||
area_map areas;
|
||||
|
||||
/// Entities without generation
|
||||
struct Entity {
|
||||
Entity(glm::vec3 size, glm::vec3 scale): size(size), scale(scale) { }
|
||||
glm::vec3 size;
|
||||
glm::vec3 scale;
|
||||
data::generational::view_vector<Universe::Entity::Instance> instances;
|
||||
};
|
||||
data::generational::view_vector<Entity> entities;
|
||||
/// Player entity instance index
|
||||
size_t playerId;
|
||||
|
||||
net::Client peer;
|
||||
std::optional<zstd::read_dict_ctx> dict;
|
||||
|
||||
|
|
|
@ -54,4 +54,24 @@ void LocalUniverse::emit(const action::packet &packet) {
|
|||
}
|
||||
Universe::ray_result LocalUniverse::raycast(const geometry::Ray& ray) const {
|
||||
return handle->raycast(ray);
|
||||
}
|
||||
|
||||
void LocalUniverse::getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>& call,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density)
|
||||
{
|
||||
std::vector<glm::mat4> mats;
|
||||
handle->entities->iter([&](entity_id eId, const Entity &entity) {
|
||||
entity.instances.iter([&](entity_id iId, const Entity::Instance &inst) {
|
||||
if (eId.index == PLAYER_ENTITY_ID.index && iId.index == PLAYER_ENTITY_ID.index)
|
||||
return;
|
||||
|
||||
glm::mat4 tmp;
|
||||
if (contouring::Abstract::CullEntity(tmp, entity.size, entity.scale, inst.pos, frustum, offset, density))
|
||||
mats.push_back(tmp);
|
||||
});
|
||||
if(!mats.empty()) {
|
||||
call(eId.index, mats);
|
||||
mats.resize(0);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -15,8 +15,13 @@ namespace world::client {
|
|||
|
||||
ray_result raycast(const geometry::Ray &ray) const override;
|
||||
|
||||
void getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>&,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density) override;
|
||||
|
||||
bool isDisconnected() const override { return !handle->running; }
|
||||
|
||||
size_t getPlayerId() const override { return PLAYER_ENTITY_ID.index; }
|
||||
|
||||
protected:
|
||||
server_handle *const handle;
|
||||
|
||||
|
|
|
@ -6,20 +6,3 @@ using namespace world::client;
|
|||
|
||||
Universe::Universe(const std::string& ct): world::Universe(), contouring(std::make_unique<contouring::FlatDualMC>(ct)) { }
|
||||
Universe::~Universe() { }
|
||||
|
||||
/*
|
||||
void ServerUniverse::getEntitiesModels(const std::function<void(const std::vector<glm::mat4>&, buffer::Abstract *const)> &draw, const std::optional<geometry::Frustum> &frustum, const glm::llvec3 &offset, int density) {
|
||||
std::vector<glm::mat4> mats;
|
||||
entities.iter([&](entity_id, const Entity &entity) {
|
||||
entity.instances.iter([&](entity_id, const Entity::Instance &inst) {
|
||||
const glm::vec3 fPos = (glm::vec3(inst.pos.raw_as_long() - offset * glm::llvec3(density)) + inst.pos.offset) / glm::vec3(density);
|
||||
if (!frustum.has_value() || frustum.value().contains(geometry::Box::fromMin(fPos, entity.size)))
|
||||
mats.emplace_back(glm::scale(glm::translate(glm::mat4(1), fPos * (float)density), entity.scale));
|
||||
});
|
||||
if(!mats.empty()) {
|
||||
draw(mats, entity.buffer.get());
|
||||
mats.resize(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
|
@ -8,6 +8,9 @@
|
|||
namespace contouring {
|
||||
class Abstract;
|
||||
}
|
||||
namespace geometry {
|
||||
struct Frustum;
|
||||
}
|
||||
namespace world::client {
|
||||
/// Whole universe container in abstract client
|
||||
class Universe: public world::Universe {
|
||||
|
@ -34,10 +37,13 @@ namespace world::client {
|
|||
return contouring.get();
|
||||
}
|
||||
|
||||
virtual bool isDisconnected() const = 0;
|
||||
/// Get entities in view
|
||||
virtual void getEntitiesModels(const std::function<void(size_t, const std::vector<glm::mat4>&)>&,
|
||||
const std::optional<geometry::Frustum>& frustum, const glm::llvec3& offset, int density) = 0;
|
||||
|
||||
//TODO: move to ClientUniverse
|
||||
//void getEntitiesModels(const std::function<void(const std::vector<glm::mat4> &, buffer::Abstract *const)> &draw, const std::optional<geometry::Frustum> &frustum, const glm::llvec3 &offset, int density);
|
||||
virtual size_t getPlayerId() const = 0;
|
||||
|
||||
virtual bool isDisconnected() const = 0;
|
||||
|
||||
protected:
|
||||
/// Contouring worker
|
||||
|
|
|
@ -228,6 +228,47 @@ namespace data::generational {
|
|||
std::vector<entry> entries;
|
||||
std::vector<size_t> freed;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class view_vector: public std::vector<std::optional<T>> {
|
||||
public:
|
||||
view_vector(): std::vector<std::optional<T>>() { }
|
||||
|
||||
template <typename... _Args>
|
||||
void set_emplace(size_t i, _Args &&... __args) {
|
||||
if(i >= this->size())
|
||||
this->resize(i + 1);
|
||||
|
||||
this->at(i).emplace(std::forward<_Args>(__args)...);
|
||||
}
|
||||
void set(size_t i, const T& in) {
|
||||
if(i >= this->size())
|
||||
this->resize(i + 1);
|
||||
|
||||
this->at(i) = in;
|
||||
}
|
||||
|
||||
T* get(size_t i) {
|
||||
if (i >= this->size() || !this->at(i).has_value())
|
||||
return nullptr;
|
||||
|
||||
return &this->at(i).value();
|
||||
}
|
||||
|
||||
template<typename apply>
|
||||
void iter(apply fn) const {
|
||||
for (size_t i = 0; i < this->size(); i++) {
|
||||
if(this->at(i).has_value()) {
|
||||
fn(i, this->at(i).value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t count() const {
|
||||
return std::count_if(this->begin(), this->end(),
|
||||
[](const std::optional<T> &e) { return e.has_value(); });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
|
|
@ -28,8 +28,8 @@ enum class server_packet_type: enet_uint8 {
|
|||
/// Get server salt
|
||||
/// reliable
|
||||
CHALLENGE = 0,
|
||||
/// Set client position
|
||||
/// voxel_pos reliable
|
||||
/// Set client position and instance id
|
||||
/// size_t(playerId) voxel_pos reliable
|
||||
TELEPORT = 1,
|
||||
|
||||
BROADCASTED = 16,
|
||||
|
@ -44,6 +44,15 @@ enum class server_packet_type: enet_uint8 {
|
|||
/// FIXME: to big !!! MAYBE: compress
|
||||
EDITS = 18,
|
||||
|
||||
/// Declare entities types
|
||||
/// {size_t(index), vec3(size), vec3(scale)} reliable
|
||||
/// TODO: zstd<chunk rle>
|
||||
ENTITY_TYPES = 20,
|
||||
|
||||
/// Update entities instances position and velocity
|
||||
/// {size_t(entity), size_t(count), {size_t(index), ifvec3(pos), vec3(velocity)}[]}[] notify
|
||||
ENTITIES = 21,
|
||||
|
||||
/// World compression dictionary
|
||||
/// zstd dict reliable
|
||||
COMPRESSION = 24,
|
||||
|
@ -57,8 +66,8 @@ enum class server_packet_type: enet_uint8 {
|
|||
};
|
||||
enum class client_packet_type: enet_uint8 {
|
||||
/// Interact with voxels
|
||||
/// actions::FillCube reliable
|
||||
FILL_CUBE = 0,
|
||||
/// actions::FillShape reliable
|
||||
FILL_SHAPE = 0,
|
||||
|
||||
/// Request missing chunks
|
||||
/// area_id, chunk_pos[] reliable
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
struct server_handle {
|
||||
bool running = false;
|
||||
const world::client::area_map *areas;
|
||||
const data::generational::vector<world::Universe::Entity> *entities;
|
||||
std::function<void(const area_<chunk_pos> &pos, const chunk_pos &offset, const world::ChunkContainer &data, geometry::Faces neighbors)> onUpdate;
|
||||
std::function<void(const world::action::packet &packet)> emit;
|
||||
std::function<world::Universe::ray_result(const geometry::Ray &ray)> raycast;
|
||||
|
|
|
@ -17,10 +17,28 @@ struct Fill: part::Ping {
|
|||
const area_<voxel_pos> pos;
|
||||
const Voxel val;
|
||||
};
|
||||
struct FillCube: Fill {
|
||||
FillCube(const area_<voxel_pos> &pos, const Voxel &val, int radius): Fill(pos, val), radius(radius) { }
|
||||
enum class Shape : uint8_t {
|
||||
Cube,
|
||||
Sphere,
|
||||
/*SmoothSphere,
|
||||
CylinderX,
|
||||
CylinderY,
|
||||
CylinderZ,
|
||||
ConePX,
|
||||
ConeNX,
|
||||
ConePY,
|
||||
ConeNY,
|
||||
ConePZ,
|
||||
ConeNZ,
|
||||
*/
|
||||
};
|
||||
constexpr auto SHAPES = "Cube\0Sphere\0";
|
||||
struct FillShape: Fill {
|
||||
FillShape(const area_<voxel_pos> &pos, const Voxel &val, Shape shape, uint8_t radius):
|
||||
Fill(pos, val), shape(shape), radius(radius) {}
|
||||
|
||||
const int radius;
|
||||
const Shape shape;
|
||||
const uint8_t radius;
|
||||
};
|
||||
struct Move: part::Ping {
|
||||
Move(const voxel_pos& pos): pos(pos) { }
|
||||
|
@ -33,5 +51,5 @@ struct Message: part::Ping {
|
|||
const std::string text;
|
||||
};
|
||||
|
||||
using packet = std::variant<Move, Message, Fill, FillCube>;
|
||||
using packet = std::variant<Move, Message, Fill, FillShape>;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
* \file model_contouring.cpp
|
||||
* \brief Generate entities vertices
|
||||
* \author Maelys Bois
|
||||
* \version 0.0.1
|
||||
*
|
||||
* Generate ShortIndexed::Data for manually defined chunks.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include "world/generator.hpp"
|
||||
#include "world/Chunk.hpp"
|
||||
#include "contouring/FlatDualMC.hpp"
|
||||
|
||||
class Contouring: public contouring::FlatDualMC {
|
||||
public:
|
||||
Contouring() : FlatDualMC("iso = 0.1\nkeep_distance = 2\nload_distance = 1\nlod_levels = [ false, false, false, false, true ]\nlod_quality = 0.0\nlod_strength = 0.15\nmanifold = true\nreordering = true\ntransparency = true") { }
|
||||
void render(const std::shared_ptr<world::Chunk>& chunk, buffer::LodShortIndexed::LodData& out) const {
|
||||
contouring::surrounding::corners surround = {
|
||||
chunk, world::EMPTY_CHUNK, world::EMPTY_CHUNK, world::EMPTY_CHUNK,
|
||||
world::EMPTY_CHUNK, world::EMPTY_CHUNK, world::EMPTY_CHUNK, world::EMPTY_CHUNK
|
||||
};
|
||||
std::vector<buffer::VertexData> tmp;
|
||||
FlatDualMC::render(surround, out, tmp);
|
||||
}
|
||||
};
|
||||
|
||||
/// Entry point
|
||||
int main(int /*unused*/, char * /*unused*/[])
|
||||
{
|
||||
const auto generator = world::generator::load(world::generator::Void::Params());
|
||||
const auto chunk = std::make_shared<world::Chunk>(chunk_pos(0), generator);
|
||||
|
||||
//TODO: load from file
|
||||
for (auto x = 1; x <= 6; x++) {
|
||||
for (auto y = 1; y <= 6; y++) {
|
||||
for (auto z = 1; z <= 6; z++) {
|
||||
chunk->setAt(chunk_voxel_pos(x, y, z), world::Voxel(z >= 4 ? world::materials::ROCK : world::materials::GRASS, world::Voxel::DENSITY_MAX));
|
||||
}}}
|
||||
|
||||
buffer::LodShortIndexed::LodData data;
|
||||
Contouring ct = Contouring();
|
||||
ct.render(chunk, data);
|
||||
assert(data.second.size() == 1 && "Must contain a single lod");
|
||||
data.first.indices.resize(data.second.front()); //Discard full res
|
||||
|
||||
std::ofstream out("content/model.ivb");
|
||||
data.first.serialize(out);
|
||||
out.close();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -6,17 +6,19 @@ using namespace world::server;
|
|||
SharedUniverse::SharedUniverse(const options &o, server_handle *const localHandle): Universe(o), localHandle(localHandle) {
|
||||
// Local player
|
||||
[[maybe_unused]]
|
||||
const auto id = entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{spawnPoint});
|
||||
const auto id = entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{spawnPoint, glm::vec3(0)});
|
||||
assert(id == PLAYER_ENTITY_ID);
|
||||
localHandle->teleport = spawnPoint;
|
||||
movedPlayers.insert(id);
|
||||
|
||||
localHandle->areas = (world::client::area_map*)(&areas); //WONT FIX: templated area
|
||||
localHandle->entities = &entities;
|
||||
localHandle->emit = std::function([&](const world::action::packet &packet) {
|
||||
if(const auto fill = std::get_if<world::action::Fill>(&packet)) {
|
||||
this->set(fill->pos, fill->val);
|
||||
} else if(const auto fillCube = std::get_if<world::action::FillCube>(&packet)) {
|
||||
this->setCube(fillCube->pos, fillCube->val, fillCube->radius);
|
||||
if(const auto fill = std::get_if<world::action::FillShape>(&packet)) {
|
||||
if (fill->shape == world::action::Shape::Cube)
|
||||
this->setCube(fill->pos, fill->val, fill->radius);
|
||||
else
|
||||
this->setSphere(fill->pos, fill->val, fill->radius);
|
||||
} else if(const auto message = std::get_if<world::action::Message>(&packet)) {
|
||||
this->broadcastMessage("Player" + std::to_string(id.index) + ": " + message->text);
|
||||
} else if(const auto move = std::get_if<world::action::Move>(&packet)) {
|
||||
|
|
|
@ -324,29 +324,45 @@ void Universe::update(float deltaTime) {
|
|||
TracyPlot("ChunkUnload", static_cast<int64_t>(saveQueue.size()));
|
||||
#endif
|
||||
}
|
||||
/* FIXME: { // Update entities
|
||||
{ // Update entities
|
||||
ZoneScopedN("Entities");
|
||||
#if TRACY_ENABLE
|
||||
size_t entity_count = 0;
|
||||
#endif
|
||||
size_t item_count = 0;
|
||||
entities.for_each([&](entity_id type, Entity &val) {
|
||||
if (type == PLAYER_ENTITY_ID) //FIXME: update players
|
||||
return;
|
||||
|
||||
val.instances.remove([&](entity_id, Entity::Instance &inst) {
|
||||
#if TRACY_ENABLE
|
||||
entity_count++;
|
||||
#endif
|
||||
if (type == PLAYER_ENTITY_ID) {
|
||||
//MAYBE: update players ?
|
||||
item_count++;
|
||||
return false;
|
||||
}
|
||||
|
||||
inst.pos += inst.velocity * deltaTime;
|
||||
return glm::length2(glm::divide(pos - inst.pos.as_voxel())) > glm::pow2(keepDistance);
|
||||
if (true /*FIXME: remove far entities ? glm::length2(glm::divide(pos - inst.pos.as_voxel())) <= glm::pow2(keepDistance);*/) {
|
||||
item_count++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
//MAYBE: Store in region ?
|
||||
//MAYBE: Save to files
|
||||
});
|
||||
});
|
||||
#if TRACY_ENABLE
|
||||
TracyPlot("EntityCount", static_cast<int64_t>(entity_count));
|
||||
#endif
|
||||
}*/
|
||||
TracyPlot("EntityCount", static_cast<int64_t>(item_count));
|
||||
|
||||
constexpr auto CAT_SIZE = sizeof(entity_id::index) + sizeof(size_t);
|
||||
constexpr auto ITEM_SIZE = sizeof(entity_id::index) + sizeof(glm::ifvec3) + sizeof(glm::vec3);
|
||||
auto packet = net::Server::makePacket(net::server_packet_type::ENTITIES, NULL, CAT_SIZE * entities.size() + ITEM_SIZE * item_count, 0);
|
||||
entities.iter([&](entity_id id, const Entity &entity) {
|
||||
packet.write(id.index);
|
||||
packet.write(entity.instances.size());
|
||||
entity.instances.iter([&](entity_id i, const Entity::Instance &inst) {
|
||||
packet.write(i.index);
|
||||
packet.write(inst.pos);
|
||||
packet.write(inst.velocity);
|
||||
});
|
||||
});
|
||||
|
||||
assert(packet.isFull());
|
||||
host.broadcast(packet.get(), net::channel_type::RELIABLE);
|
||||
}
|
||||
|
||||
{ // Store loaded chunks
|
||||
ZoneScopedN("Load");
|
||||
|
@ -375,7 +391,7 @@ void Universe::pullNetwork() {
|
|||
[&](peer_t *peer, salt_t salt) {
|
||||
ZoneScopedN("Connect");
|
||||
LOG_I("Client connect from " << peer->address);
|
||||
net_client* client = new net_client(salt, entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{spawnPoint}));
|
||||
net_client* client = new net_client(salt, entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{spawnPoint, glm::vec3(0)}));
|
||||
peer->data = client;
|
||||
|
||||
const salt_t rnd = std::rand();
|
||||
|
@ -386,9 +402,22 @@ void Universe::pullNetwork() {
|
|||
host.send(peer, server_packet_type::COMPRESSION, dict_content.data(), dict_content.size(), channel_type::RELIABLE);
|
||||
{
|
||||
auto player = findEntity(PLAYER_ENTITY_ID, client->instanceId);
|
||||
host.sendTo(peer, server_packet_type::TELEPORT, player->pos.as_voxel(), channel_type::RELIABLE);
|
||||
struct tp { size_t bindEntity; voxel_pos position; };
|
||||
host.sendTo(peer, server_packet_type::TELEPORT, tp{client->instanceId.index, player->pos.as_voxel()}, channel_type::RELIABLE);
|
||||
movedPlayers.insert(client->instanceId);
|
||||
}
|
||||
{
|
||||
constexpr auto ITEM_SIZE = sizeof(entity_id::index) + sizeof(glm::vec3) * 2;
|
||||
auto packet = net::Server::makePacket(net::server_packet_type::ENTITY_TYPES, NULL, ITEM_SIZE * entities.size(), ENET_PACKET_FLAG_RELIABLE);
|
||||
entities.iter([&](entity_id id, const Entity &entity) {
|
||||
packet.write(id.index);
|
||||
packet.write(entity.size);
|
||||
packet.write(entity.scale);
|
||||
});
|
||||
|
||||
assert(packet.isFull());
|
||||
host.broadcast(packet.get(), net::channel_type::RELIABLE);
|
||||
}
|
||||
broadcastMessage("> Player" + std::to_string(client->instanceId.index) + " has joined us");
|
||||
broadcastAreas();
|
||||
},
|
||||
|
@ -422,10 +451,15 @@ void Universe::pullNetwork() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case client_packet_type::FILL_CUBE: {
|
||||
if(const auto fill = PacketReader(packet).read<world::action::FillCube>()) {
|
||||
case client_packet_type::FILL_SHAPE: {
|
||||
if(const auto fill = PacketReader(packet).read<world::action::FillShape>()) {
|
||||
//TODO: check ray
|
||||
//TODO: check entities
|
||||
//TODO: handle inventory
|
||||
setCube(fill->pos, fill->val, fill->radius);
|
||||
if (fill->shape == world::action::Shape::Cube)
|
||||
setCube(fill->pos, fill->val, fill->radius);
|
||||
else
|
||||
setSphere(fill->pos, fill->val, fill->radius);
|
||||
} else {
|
||||
LOG_T("Bad fill");
|
||||
}
|
||||
|
@ -496,7 +530,7 @@ void Universe::broadcastMessage(const std::string& text) {
|
|||
host.broadcast(net::server_packet_type::MESSAGE, text.data(), text.size(), net::channel_type::RELIABLE);
|
||||
}
|
||||
|
||||
void Universe::updateChunk(area_map::iterator &, world::ChunkContainer::iterator &, chunk_pos, float deltaTime) {}
|
||||
void Universe::updateChunk(area_map::iterator &, world::ChunkContainer::iterator &, chunk_pos, float /*deltaTime*/) {}
|
||||
void Universe::loadChunk(area_<chunk_pos>, chunk_pos, const world::ChunkContainer &) {}
|
||||
|
||||
void Universe::setOptions(const Universe::options& options) {
|
||||
|
@ -563,6 +597,55 @@ world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val,
|
|||
}
|
||||
return list;
|
||||
}
|
||||
world::ItemList Universe::setSphere(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
|
||||
ZoneScopedN("FillSphere");
|
||||
ItemList list;
|
||||
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
robin_hood::unordered_map<chunk_pos, std::vector<Chunk::Edit>> edits;
|
||||
auto &chunks = it->second->setChunks();
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
const auto offset = voxel_pos(x, y, z);
|
||||
//FIXME: refactor with voxel_pos iterator
|
||||
if (glm::length2(offset) > glm::pow2(radius))
|
||||
continue;
|
||||
|
||||
//TODO: list.pop(val)
|
||||
const auto split = glm::splitIdx(pos.second + offset);
|
||||
if(chunks.inRange(split.first))
|
||||
if(const auto chunk = it->second->setChunks().findInRange(split.first)) {
|
||||
auto ck = std::dynamic_pointer_cast<Chunk>(chunk.value());
|
||||
auto prev = ck->get(split.second);
|
||||
if(prev.value != val.value) {
|
||||
//TODO: apply break table
|
||||
//TODO: inventory
|
||||
const auto delay = glm::length2(offset) / radius * .05f;
|
||||
edits[split.first].push_back(Chunk::Edit{split.second, val, delay});
|
||||
ck->replace(split.second, val, delay);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
ZoneScopedN("Packet");
|
||||
size_t size = sizeof(area_id);
|
||||
for(const auto& part: edits) {
|
||||
size += sizeof(chunk_pos);
|
||||
size += sizeof(chunk_voxel_idx);
|
||||
size += sizeof(Chunk::Edit) * part.second.size();
|
||||
}
|
||||
auto packet = net::Server::makePacket(net::server_packet_type::EDITS, NULL, size, 0);
|
||||
packet.write(pos.first);
|
||||
for(const auto& part: edits) {
|
||||
packet.write(part.first);
|
||||
packet.write<chunk_voxel_idx>(part.second.size());
|
||||
packet.write(part.second.data(), part.second.size() * sizeof(Chunk::Edit));
|
||||
}
|
||||
|
||||
assert(packet.isFull());
|
||||
host.broadcast(packet.get(), net::channel_type::NOTIFY);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
bool Universe::collide_end(const glm::ifvec3 &pos, const glm::vec3 &vel, int density, float radius) const {
|
||||
return std::holds_alternative<ray_target>(raycast(geometry::Ray((pos + vel) * density, vel, radius)));
|
||||
|
|
|
@ -44,6 +44,9 @@ namespace world::server {
|
|||
/// Set cube of voxel with pos as center
|
||||
/// MAYBE: allow set multi area
|
||||
ItemList setCube(const area_<voxel_pos> &pos, const Voxel &val, int radius);
|
||||
/// Set sphere of voxel with pos as center
|
||||
/// MAYBE: allow set multi area
|
||||
ItemList setSphere(const area_<voxel_pos> &pos, const Voxel &val, int radius);
|
||||
|
||||
/// Instante entity
|
||||
entity_instance_id addEntity(entity_id type, const Entity::Instance &instance);
|
||||
|
@ -76,7 +79,6 @@ namespace world::server {
|
|||
virtual std::shared_ptr<Chunk> createChunk(const chunk_pos &pos, const std::unique_ptr<generator::Abstract> &rnd) const;
|
||||
virtual std::shared_ptr<Chunk> createChunk(std::istream &str) const;
|
||||
|
||||
|
||||
virtual void updateChunk(area_map::iterator&, world::ChunkContainer::iterator&, chunk_pos, float deltaTime);
|
||||
virtual void loadChunk(area_<chunk_pos>, chunk_pos, const world::ChunkContainer &);
|
||||
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/**
|
||||
* \file zstd_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 <ctime>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <zstd.h>
|
||||
#include <zdict.h>
|
||||
|
||||
const auto KB = 1000;
|
||||
const auto COUNT = 100;
|
||||
const auto SIZE = COUNT * KB;
|
||||
const auto SAMPLES = 100;
|
||||
const auto RANGE = 1 << 18;
|
||||
|
||||
/// Entry point
|
||||
int main(int /*unused*/, char * /*unused*/[])
|
||||
{
|
||||
std::srand(std::time(nullptr));
|
||||
auto generator = world::generator::load(world::generator::Cave::Params(std::rand()));
|
||||
std::vector<char> samples;
|
||||
samples.reserve(SIZE * SAMPLES);
|
||||
std::vector<size_t> sizes;
|
||||
sizes.reserve(SAMPLES * 10);
|
||||
std::cout << "Generating..." << std::endl;
|
||||
std::chrono::nanoseconds gen_time(0);
|
||||
while(samples.size() < SIZE * SAMPLES) {
|
||||
const auto start = std::chrono::high_resolution_clock::now();
|
||||
world::Chunk chunk(chunk_pos(-(std::rand() % RANGE), -(std::rand() % RANGE), -(std::rand() % RANGE)), generator);
|
||||
gen_time += (std::chrono::high_resolution_clock::now() - start);
|
||||
std::ostringstream oss;
|
||||
chunk.write(oss);
|
||||
const auto str = oss.str();
|
||||
samples.insert(samples.end(), str.begin(), str.end());
|
||||
sizes.push_back(str.size());
|
||||
}
|
||||
std::cout << gen_time.count() / sizes.size() << "ns/chunk" << std::endl;
|
||||
|
||||
std::vector<char> dict(SIZE);
|
||||
std::cout << "Training on " << sizes.size() << " samples..." << std::endl;
|
||||
const auto actualSize = ZDICT_trainFromBuffer(dict.data(), dict.size(), samples.data(), sizes.data(), sizes.size());
|
||||
if(ZSTD_isError(actualSize)) {
|
||||
std::cout << "Error: " << ZSTD_getErrorName(actualSize) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Dictionary of " << actualSize / KB << "kb" << std::endl;
|
||||
std::ofstream out("content/zstd.dict");
|
||||
out.write(dict.data(), actualSize);
|
||||
out.close();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue