1
0
Fork 0

Player's entities

mingw
May B. 2020-10-23 15:19:44 +02:00
parent 7920e8b473
commit 686505bded
33 changed files with 330 additions and 178 deletions

View File

@ -25,12 +25,16 @@
- [ ] Contouring service
- [~] Edit
- [ ] More types
- Sphere
- Anchor
- Prevent suffocation
- [ ] Local prediction
- [~] Occlusion Culling
- [ ] Iterator ray
- [ ] Cast from chunk center
- [x] Transparency
- [ ] Entities
- [~] Entities
- Get models
## Hello universe
@ -63,6 +67,7 @@
## Hello darkness
- [ ] Break area part to entity
- [ ] Slash screen
- [ ] Start/Pause menu
- [ ] QUIC protocal
@ -70,7 +75,7 @@
- [ ] Octree
- [ ] Better Lod
- [ ] VK
- [ ] Pipeline recreate
- [ ] Instanced draw
- [ ] Pipeline cache
- [ ] Reuse descriptors
- [ ] Secondary buffers

View File

@ -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)

Binary file not shown.

BIN
resource/content/shaders/Voxel.geo.fs.spv (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
resource/content/shaders/Voxel.ins.fs.spv (Stored with Git LFS)

Binary file not shown.

View File

@ -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

View File

@ -183,11 +183,13 @@ 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();

View File

@ -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;
};
};
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -87,6 +87,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;
}

View File

@ -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);
}

View File

@ -42,6 +42,8 @@ public:
Model(const Data&);
~Model();
static void MakeDefault();
size_t draw();
size_t drawInstanced(size_t count);

View File

@ -315,7 +315,23 @@ 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);

View File

@ -26,7 +26,8 @@ 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);
void recordPostprocess(uint32_t idx, const Subpass&, bool skybox);

View File

@ -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; }

View File

@ -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,10 +472,14 @@ 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() {

View File

@ -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);
}

View File

@ -71,8 +71,12 @@ protected:
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;

View File

@ -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;
@ -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);
}
});
}

View File

@ -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;

View File

@ -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);
}
});
}

View File

@ -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;

View File

@ -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);
}
});
}
*/

View File

@ -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

View File

@ -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 {

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -12,6 +12,7 @@ SharedUniverse::SharedUniverse(const options &o, server_handle *const localHandl
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);

View File

@ -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");
@ -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();
},
@ -424,6 +453,8 @@ void Universe::pullNetwork() {
}
case client_packet_type::FILL_CUBE: {
if(const auto fill = PacketReader(packet).read<world::action::FillCube>()) {
//TODO: check ray
//TODO: check entities
//TODO: handle inventory
setCube(fill->pos, fill->val, fill->radius);
} else {

View File

@ -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;
}