From 4bdbbdbe2ff76ec6084f76b4371557e20771c25d Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Wed, 10 Sep 2025 21:09:37 +0600 Subject: [PATCH] * --- Src/Client/ServerSession.cpp | 3 + Src/Client/Vulkan/VulkanRenderSession.cpp | 29 +++++ Src/Client/Vulkan/VulkanRenderSession.hpp | 132 +++++++++++++--------- Src/Common/Abstract.cpp | 55 +++++---- Src/Common/Abstract.hpp | 94 ++++++++++----- 5 files changed, 205 insertions(+), 108 deletions(-) diff --git a/Src/Client/ServerSession.cpp b/Src/Client/ServerSession.cpp index 4607f0a..6e46e25 100644 --- a/Src/Client/ServerSession.cpp +++ b/Src/Client/ServerSession.cpp @@ -761,6 +761,7 @@ void ServerSession::update(GlobalTime gTime, float dTime) { auto iter = MyAssets.NotInUse[(int) entry.Type].find(entry.Domain+':'+entry.Key); if(iter != MyAssets.NotInUse[(int) entry.Type].end()) { IServerSession::Assets[entry.Type][entry.Id] = std::get<0>(iter->second); + result.Assets_ChangeOrAdd[entry.Type].push_back(entry.Id); MyAssets.NotInUse[(int) entry.Type].erase(iter); } } @@ -774,6 +775,7 @@ void ServerSession::update(GlobalTime gTime, float dTime) { if(iter != IServerSession::Assets[(EnumAssets) type].end()) { MyAssets.NotInUse[(int) iter->second.Type][iter->second.Domain+':'+iter->second.Key] = {iter->second, TIME_BEFORE_UNLOAD_RESOURCE+time(nullptr)}; IServerSession::Assets[(EnumAssets) type].erase(iter); + result.Assets_Lost[iter->second.Type].push_back(iter->second.Id); } } @@ -787,6 +789,7 @@ void ServerSession::update(GlobalTime gTime, float dTime) { if(MyAssets.ExistBinds[(int) entry.Type].contains(entry.Id)) { // Ресурс ещё нужен IServerSession::Assets[entry.Type][entry.Id] = entry; + result.Assets_ChangeOrAdd[entry.Type].push_back(entry.Id); } else { // Ресурс уже не нужен, отправляем в кеш MyAssets.NotInUse[(int) entry.Type][entry.Domain+':'+entry.Key] = {entry, TIME_BEFORE_UNLOAD_RESOURCE+time(nullptr)}; diff --git a/Src/Client/Vulkan/VulkanRenderSession.cpp b/Src/Client/Vulkan/VulkanRenderSession.cpp index ed9d31f..7ff0147 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.cpp +++ b/Src/Client/Vulkan/VulkanRenderSession.cpp @@ -1460,6 +1460,35 @@ void VulkanRenderSession::tickSync(const TickSyncData& data) { mcpData.ChangedChunks = data.Chunks_ChangeOrAdd; mcpData.LostRegions = data.Chunks_Lost; CP.tickSync(mcpData); + + { + std::vector> resources; + std::vector lost; + + for(const auto& [type, ids] : data.Assets_ChangeOrAdd) { + if(type != EnumAssets::Model) + continue; + + const auto& list = ServerSession->Assets[type]; + for(ResourceId id : ids) { + auto iter = list.find(id); + if(iter == list.end()) + continue; + + resources.emplace_back(id, iter->second.Res); + } + } + + for(const auto& [type, ids] : data.Assets_Lost) { + if(type != EnumAssets::Model) + continue; + + lost.append_range(ids); + } + + if(!resources.empty() || !lost.empty()) + MP.onModelChanges(std::move(resources), std::move(lost)); + } } void VulkanRenderSession::setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) { diff --git a/Src/Client/Vulkan/VulkanRenderSession.hpp b/Src/Client/Vulkan/VulkanRenderSession.hpp index a917bd1..2595099 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.hpp +++ b/Src/Client/Vulkan/VulkanRenderSession.hpp @@ -19,6 +19,7 @@ #include "Abstract.hpp" #include "TOSLib.hpp" #include "VertexPool.hpp" +#include "glm/common.hpp" #include "glm/fwd.hpp" #include "../FrustumCull.h" #include "glm/geometric.hpp" @@ -53,51 +54,6 @@ struct WorldPCO { static_assert(sizeof(WorldPCO) == 128); class ModelProvider { - struct Transformations { - std::vector OPs; - - void apply(std::vector& vertices) const { - if (vertices.empty() || OPs.empty()) - return; - - glm::mat4 transform(1.0f); - - for (const auto& op : OPs) { - switch (op.Op) { - case Transformation::MoveX: transform = glm::translate(transform, glm::vec3(op.Value, 0.0f, 0.0f)); break; - case Transformation::MoveY: transform = glm::translate(transform, glm::vec3(0.0f, op.Value, 0.0f)); break; - case Transformation::MoveZ: transform = glm::translate(transform, glm::vec3(0.0f, 0.0f, op.Value)); break; - case Transformation::ScaleX: transform = glm::scale(transform, glm::vec3(op.Value, 1.0f, 1.0f)); break; - case Transformation::ScaleY: transform = glm::scale(transform, glm::vec3(1.0f, op.Value, 1.0f)); break; - case Transformation::ScaleZ: transform = glm::scale(transform, glm::vec3(1.0f, 1.0f, op.Value)); break; - case Transformation::RotateX: transform = glm::rotate(transform, op.Value, glm::vec3(1.0f, 0.0f, 0.0f)); break; - case Transformation::RotateY: transform = glm::rotate(transform, op.Value, glm::vec3(0.0f, 1.0f, 0.0f)); break; - case Transformation::RotateZ: transform = glm::rotate(transform, op.Value, glm::vec3(0.0f, 0.0f, 1.0f)); break; - default: break; - } - } - - std::transform( - std::execution::unseq, - vertices.begin(), - vertices.end(), - vertices.begin(), - [transform](Vertex v) -> Vertex { - glm::vec4 pos_h(v.Pos, 1.0f); - pos_h = transform * pos_h; - v.Pos = glm::vec3(pos_h) / pos_h.w; - return v; - } - ); - } - - std::vector apply(const std::vector& vertices) const { - std::vector result = vertices; - apply(result); - return result; - } - }; - struct Model { // В вершинах текущей модели TexId ссылается на локальный текстурный ключ // 0 -> default_texture -> luavox:grass.png @@ -191,26 +147,92 @@ public: if(data.starts_with((const char8_t*) "bm")) { type = "InternalBinary"; // Компилированная модель внутреннего формата - LV::PreparedModel pm((std::u8string) data.substr(2)); + LV::PreparedModel pm((std::u8string) data); + model.TextureMap = pm.CompiledTextures; model.TextureKeys = {}; for(const PreparedModel::Cuboid& cb : pm.Cuboids) { + glm::vec3 min = glm::min(cb.From, cb.To), max = glm::max(cb.From, cb.To); + + for(const auto& [face, params] : cb.Faces) { - // params. + glm::vec2 from_uv = {params.UV[0], params.UV[1]}, to_uv = {params.UV[2], params.UV[3]}; + + uint32_t texId; + { + auto iter = std::find(model.TextureKeys.begin(), model.TextureKeys.end(), params.Texture); + if(iter == model.TextureKeys.end()) { + texId = model.TextureKeys.size(); + model.TextureKeys.push_back(params.Texture); + } else { + texId = iter-model.TextureKeys.begin(); + } + } + + std::vector v; + + switch(face) { + case EnumFace::Down: + v.emplace_back(glm::vec3{min.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, min.y, max.z}, glm::vec2{from_uv.x, to_uv.y}, texId); + v.emplace_back(glm::vec3{max.x, min.y, min.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{min.x, min.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{max.x, min.y, max.z}, glm::vec2{to_uv.x, from_uv.y}, texId); + break; + case EnumFace::Up: + v.emplace_back(glm::vec3{min.x, max.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, max.y, min.z}, glm::vec2{from_uv.x, to_uv.y}, texId); + v.emplace_back(glm::vec3{max.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, max.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, max.y, max.z}, glm::vec2{to_uv.x, from_uv.y}, texId); + break; + case EnumFace::North: + v.emplace_back(glm::vec3{min.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, min.y, min.z}, glm::vec2{from_uv.x, to_uv.y}, texId); + v.emplace_back(glm::vec3{max.x, max.y, min.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, max.y, min.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, max.y, min.z}, glm::vec2{to_uv.x, from_uv.y}, texId); + break; + case EnumFace::South: + v.emplace_back(glm::vec3{min.x, min.y, max.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, min.y, max.z}, glm::vec2{from_uv.x, to_uv.y}, texId); + v.emplace_back(glm::vec3{max.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, min.y, max.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, max.y, max.z}, glm::vec2{to_uv.x, from_uv.y}, texId); + break; + case EnumFace::West: + v.emplace_back(glm::vec3{min.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{min.x, min.y, max.z}, glm::vec2{from_uv.x, to_uv.y}, texId); + v.emplace_back(glm::vec3{min.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{min.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{min.x, max.y, min.z}, glm::vec2{to_uv.x, from_uv.y}, texId); + break; + case EnumFace::East: + v.emplace_back(glm::vec3{max.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, min.y, max.z}, glm::vec2{from_uv.x, to_uv.y}, texId); + v.emplace_back(glm::vec3{max.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{max.x, min.y, min.z}, from_uv, texId); + v.emplace_back(glm::vec3{max.x, max.y, max.z}, to_uv, texId); + v.emplace_back(glm::vec3{max.x, max.y, min.z}, glm::vec2{to_uv.x, from_uv.y}, texId); + break; + default: + MAKE_ERROR("EnumFace::None"); + } + + cb.Trs.apply(v); + model.Vertecies[params.Cullface].append_range(v); } } - // glm::vec3 From, To; - // struct Face { - // glm::vec4 UV; - // std::string Texture; - // std::optional Cullface; // int TintIndex = -1; // int16_t Rotation = 0; // }; - - // std::unordered_map Faces; // std::vector Transformations; @@ -231,7 +253,6 @@ public: lock->insert({key, std::move(model)}); } - std::sort(result.begin(), result.end()); auto eraseIter = std::unique(result.begin(), result.end()); result.erase(eraseIter, result.end()); @@ -559,6 +580,7 @@ class VulkanRenderSession : public IRenderSession { glm::quat Quat; ChunkPreparator CP; + ModelProvider MP; AtlasImage MainTest, LightDummy; Buffer TestQuad; diff --git a/Src/Common/Abstract.cpp b/Src/Common/Abstract.cpp index db9c139..2bbf2dd 100644 --- a/Src/Common/Abstract.cpp +++ b/Src/Common/Abstract.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -981,6 +982,7 @@ PreparedNodeState::PreparedNodeState(const std::u8string& data) { } } + lr.checkUnreaded(); } std::u8string PreparedNodeState::dump() const { @@ -1502,7 +1504,7 @@ std::pair PreparedNodeState::parseTransormations(const js::array& arr) { +std::vector PreparedNodeState::parseTransormations(const js::array& arr) { std::vector result; for(const js::value& js_value : arr) { @@ -1721,21 +1723,23 @@ PreparedModel::PreparedModel(const std::string_view modid, const js::object& pro } if(key == "x") - result.Transformations.emplace_back(Transformation::MoveX, f_value); + result.Trs.OPs.emplace_back(Transformation::MoveX, f_value); else if(key == "y") - result.Transformations.emplace_back(Transformation::MoveY, f_value); + result.Trs.OPs.emplace_back(Transformation::MoveY, f_value); else if(key == "z") - result.Transformations.emplace_back(Transformation::MoveZ, f_value); + result.Trs.OPs.emplace_back(Transformation::MoveZ, f_value); else if(key == "rx") - result.Transformations.emplace_back(Transformation::RotateX, f_value); + result.Trs.OPs.emplace_back(Transformation::RotateX, f_value); else if(key == "ry") - result.Transformations.emplace_back(Transformation::RotateY, f_value); + result.Trs.OPs.emplace_back(Transformation::RotateY, f_value); else if(key == "rz") - result.Transformations.emplace_back(Transformation::RotateZ, f_value); + result.Trs.OPs.emplace_back(Transformation::RotateZ, f_value); else MAKE_ERROR("Неизвестный ключ трансформации"); } } + + Cuboids.emplace_back(std::move(result)); } } @@ -1771,6 +1775,8 @@ PreparedModel::PreparedModel(const std::string_view modid, const sol::table& pro PreparedModel::PreparedModel(const std::u8string& data) { Net::LinearReader lr(data); + lr.read(); + if(lr.read()) { GuiLight = (EnumGuiLight) lr.read(); } @@ -1811,8 +1817,8 @@ PreparedModel::PreparedModel(const std::u8string& data) { lr >> size; Textures.reserve(size); for(int counter = 0; counter < size; counter++) { - std::string tkey, pipeline; - lr >> tkey >> pipeline; + std::string tkey; + lr >> tkey; TexturePipeline pipe; uint16_t size; @@ -1852,9 +1858,9 @@ PreparedModel::PreparedModel(const std::u8string& data) { lr >> face.Texture; uint8_t val = lr.read(); - if(val != uint8_t(-1)) { - face.Cullface = EnumFace(val); - } + face.Cullface = EnumFace(val); + if((int) face.Cullface > (int) EnumFace::None) + MAKE_ERROR("Unknown face"); lr >> face.TintIndex >> face.Rotation; @@ -1863,21 +1869,22 @@ PreparedModel::PreparedModel(const std::u8string& data) { uint16_t transformationsSize; lr >> transformationsSize; - cuboid.Transformations.reserve(transformationsSize); + cuboid.Trs.OPs.reserve(transformationsSize); for(int counter2 = 0; counter2 < transformationsSize; counter2++) { Transformation tsf; tsf.Op = (Transformation::EnumTransform) lr.read(); lr >> tsf.Value; - cuboid.Transformations.emplace_back(tsf); + cuboid.Trs.OPs.emplace_back(tsf); } Cuboids.emplace_back(std::move(cuboid)); } - lr >> size; - SubModels.reserve(size); - for(int counter = 0; counter < size; counter++) { + uint8_t size8; + lr >> size8; + SubModels.reserve(size8); + for(int counter = 0; counter < size8; counter++) { SubModel sub; lr >> sub.Domain >> sub.Key; uint16_t val = lr.read(); @@ -1887,6 +1894,8 @@ PreparedModel::PreparedModel(const std::u8string& data) { SubModels.push_back(std::move(sub)); } + + lr.checkUnreaded(); } std::u8string PreparedModel::dump() const { @@ -1964,17 +1973,14 @@ std::u8string PreparedModel::dump() const { result << face.UV[iter]; result << face.Texture; - if(face.Cullface) - result << uint8_t(*face.Cullface); - else - result << uint8_t(-1); + result << uint8_t(face.Cullface); result << face.TintIndex << face.Rotation; } - assert(cuboid.Transformations.size() < 256); - result << uint8_t(cuboid.Transformations.size()); - for(const auto& [op, value] : cuboid.Transformations) { + assert(cuboid.Trs.OPs.size() < 256); + result << uint8_t(cuboid.Trs.OPs.size()); + for(const auto& [op, value] : cuboid.Trs.OPs) { result << uint8_t(op) << value; } } @@ -2014,6 +2020,7 @@ PreparedGLTF::PreparedGLTF(const std::string_view modid, Resource glb) { PreparedGLTF::PreparedGLTF(std::u8string_view data) { + // lr.checkUnreaded(); } diff --git a/Src/Common/Abstract.hpp b/Src/Common/Abstract.hpp index f9aad47..cfd7524 100644 --- a/Src/Common/Abstract.hpp +++ b/Src/Common/Abstract.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace LV { @@ -539,6 +540,68 @@ struct NodestateEntry { std::vector ValueNames; // Имена состояний, если имеются }; +struct Vertex { + glm::vec3 Pos; + glm::vec2 UV; + uint32_t TexId; +}; + +struct Transformation { + enum EnumTransform { + MoveX, MoveY, MoveZ, + RotateX, RotateY, RotateZ, + ScaleX, ScaleY, ScaleZ, + MAX_ENUM + } Op; + + float Value; +}; + +struct Transformations { + std::vector OPs; + + void apply(std::vector& vertices) const { + if (vertices.empty() || OPs.empty()) + return; + + glm::mat4 transform(1.0f); + + for (const auto& op : OPs) { + switch (op.Op) { + case Transformation::MoveX: transform = glm::translate(transform, glm::vec3(op.Value, 0.0f, 0.0f)); break; + case Transformation::MoveY: transform = glm::translate(transform, glm::vec3(0.0f, op.Value, 0.0f)); break; + case Transformation::MoveZ: transform = glm::translate(transform, glm::vec3(0.0f, 0.0f, op.Value)); break; + case Transformation::ScaleX: transform = glm::scale(transform, glm::vec3(op.Value, 1.0f, 1.0f)); break; + case Transformation::ScaleY: transform = glm::scale(transform, glm::vec3(1.0f, op.Value, 1.0f)); break; + case Transformation::ScaleZ: transform = glm::scale(transform, glm::vec3(1.0f, 1.0f, op.Value)); break; + case Transformation::RotateX: transform = glm::rotate(transform, op.Value, glm::vec3(1.0f, 0.0f, 0.0f)); break; + case Transformation::RotateY: transform = glm::rotate(transform, op.Value, glm::vec3(0.0f, 1.0f, 0.0f)); break; + case Transformation::RotateZ: transform = glm::rotate(transform, op.Value, glm::vec3(0.0f, 0.0f, 1.0f)); break; + default: break; + } + } + + std::transform( + std::execution::unseq, + vertices.begin(), + vertices.end(), + vertices.begin(), + [transform](Vertex v) -> Vertex { + glm::vec4 pos_h(v.Pos, 1.0f); + pos_h = transform * pos_h; + v.Pos = glm::vec3(pos_h) / pos_h.w; + return v; + } + ); + } + + std::vector apply(const std::vector& vertices) const { + std::vector result = vertices; + apply(result); + return result; + } +}; + /* Хранит распаршенное определение состояний нод. Не привязано ни к какому окружению. @@ -559,16 +622,6 @@ struct PreparedNodeState { std::variant v; }; - struct Transformation { - enum EnumTransform { - MoveX, MoveY, MoveZ, - RotateX, RotateY, RotateZ, - MAX_ENUM - } Op; - - float Value; - }; - struct Model { uint16_t Id; bool UVLock = false; @@ -628,17 +681,6 @@ enum class EnumFace { Down, Up, North, South, West, East, None }; -struct Transformation { - enum EnumTransform { - MoveX, MoveY, MoveZ, - RotateX, RotateY, RotateZ, - ScaleX, ScaleY, ScaleZ, - MAX_ENUM - } Op; - - float Value; -}; - /* Парсит json модель */ @@ -668,14 +710,14 @@ struct PreparedModel { struct Face { glm::vec4 UV; std::string Texture; - std::optional Cullface; + EnumFace Cullface = EnumFace::None; int TintIndex = -1; int16_t Rotation = 0; }; std::unordered_map Faces; - std::vector Transformations; + Transformations Trs; }; std::vector Cuboids; @@ -706,12 +748,6 @@ private: void load(std::u8string_view data); }; -struct Vertex { - glm::vec3 Pos; - glm::vec2 UV; - uint32_t TexId; -}; - struct PreparedGLTF { std::vector TextureKey; std::unordered_map Textures;