Реформа ресурсов

This commit is contained in:
2025-06-27 18:44:53 +06:00
parent 4743583831
commit e083510525
4 changed files with 461 additions and 211 deletions

View File

@@ -10,6 +10,9 @@
namespace LV::Client { namespace LV::Client {
using EntityId_t = uint16_t;
using FuncEntityId_t = uint16_t;
struct GlobalTime { struct GlobalTime {
uint32_t Seconds : 22 = 0, Sub : 10 = 0; uint32_t Seconds : 22 = 0, Sub : 10 = 0;
@@ -31,12 +34,12 @@ struct GlobalTime {
}; };
struct VoxelCube { struct VoxelCube {
DefVoxelId_c VoxelId; DefVoxelId_t VoxelId;
Pos::Local256_u Left, Size; Pos::bvec256u Left, Size;
}; };
struct Node { struct Node {
DefNodeId_c NodeId; DefNodeId_t NodeId;
uint8_t Rotate : 6; uint8_t Rotate : 6;
}; };
@@ -46,16 +49,16 @@ struct Chunk {
// Кубы вокселей в чанке // Кубы вокселей в чанке
std::vector<VoxelCube> Voxels; std::vector<VoxelCube> Voxels;
// Ноды // Ноды
std::unordered_map<Pos::Local16_u, Node> Nodes; std::unordered_map<Pos::bvec16u, Node> Nodes;
// Ограничения прохождения света, идущего от солнца (от верха карты до верхней плоскости чанка) // Ограничения прохождения света, идущего от солнца (от верха карты до верхней плоскости чанка)
LightPrism Lights[16][16]; // LightPrism Lights[16][16];
}; };
class Entity { class Entity {
public: public:
// PosQuat // PosQuat
DefWorldId_c WorldId; WorldId_t WorldId;
DefPortalId_c LastUsedPortal; PortalId_t LastUsedPortal;
Pos::Object Pos; Pos::Object Pos;
glm::quat Quat; glm::quat Quat;
static constexpr uint16_t HP_BS = 4096, HP_BS_Bit = 12; static constexpr uint16_t HP_BS = 4096, HP_BS_Bit = 12;
@@ -70,10 +73,17 @@ public:
/* Интерфейс рендера текущего подключения к серверу */ /* Интерфейс рендера текущего подключения к серверу */
class IRenderSession { class IRenderSession {
public: public:
virtual void onDefTexture(TextureId_c id, std::vector<std::byte> &&info) = 0; // Подгрузка двоичных ресурсов
virtual void onDefTextureLost(const std::vector<TextureId_c> &&lost) = 0; virtual void onBinaryResourceAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, BinaryResource>>) = 0;
virtual void onDefModel(ModelId_c id, std::vector<std::byte> &&info) = 0; virtual void onBinaryResourceLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) = 0;
virtual void onDefModelLost(const std::vector<ModelId_c> &&lost) = 0;
// Профили использования двоичных ресурсов
// В этом месте нужно зарание распарсить
virtual void onBinaryProfileAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, std::u8string>>) = 0;
virtual void onBinaryProfileLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) = 0;
virtual void onContentDefines(std::unordered_map<EnumDefContent, std::unordered_map<>>);
EnumDefContent
virtual void onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) = 0; virtual void onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) = 0;
virtual void onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) = 0; virtual void onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) = 0;

View File

@@ -2,170 +2,416 @@
#include <cstdint> #include <cstdint>
#include <glm/ext.hpp> #include <glm/ext.hpp>
#include <memory>
#include <type_traits>
#include <vector>
namespace LV { namespace LV {
namespace Pos { namespace Pos {
struct Local4_u { template<typename T, size_t BitsPerComponent>
uint8_t X : 2, Y : 2, Z : 2; class BitVec3 {
static_assert(std::is_integral_v<T>, "T must be an integral type");
static_assert(BitsPerComponent > 0, "Bits per component must be at least 1");
static constexpr size_t N = 3;
using Key = uint8_t; static constexpr auto getType() {
operator Key() const { constexpr size_t bits = N*BitsPerComponent;
return Key(X) | (Key(Y) << 2) | (Key(Z) << 4); if constexpr(bits <= 8)
}; return uint8_t(0);
}; else if constexpr(bits <= 16)
return uint16_t(0);
else if constexpr(bits <= 32)
return uint32_t(0);
else if constexpr(bits <= 64)
return uint64_t(0);
else {
static_assert("Нет подходящего хранилища");
return uint8_t(0);
}
}
public:
using Pack = decltype(getType());
using Type = T;
using value_type = Type;
struct Local16_u { T x : BitsPerComponent, y : BitsPerComponent, z : BitsPerComponent;
uint8_t X : 4, Y : 4, Z : 4;
using Key = uint16_t; public:
operator Key() const { BitVec3() = default;
return Key(X) | (Key(Y) << 4) | (Key(Z) << 8); BitVec3(T value)
}; : x(value), y(value), z(value)
{
}
BitVec3(const T x, const T y, const T z)
: x(x), y(y), z(z)
{}
BitVec3(const BitVec3&) = default;
BitVec3(BitVec3&&) = default;
BitVec3& operator=(const BitVec3&) = default;
BitVec3& operator=(BitVec3&&) = default;
void set(size_t index, const T value) {
assert(index < N);
if(index == 0)
x = value;
else if(index == 1)
y = value;
else if(index == 2)
z = value;
}
const T get(size_t index) const {
assert(index < N);
if(index == 0)
return x;
else if(index == 1)
return y;
else if(index == 2)
return z;
return 0;
}
const T operator[](size_t index) const {
return get(index);
}
Pack pack() const requires (N*BitsPerComponent <= 64) {
Pack out = 0;
using U = std::make_unsigned_t<T>;
for(size_t iter = 0; iter < N; iter++) {
out |= Pack(U(get(iter))) << BitsPerComponent*iter;
}
return out;
}
void unpack(const Pack pack) requires (N*BitsPerComponent <= 64) {
using U = std::make_unsigned_t<T>;
for(size_t iter = 0; iter < N; iter++) {
get(iter) = U((pack >> BitsPerComponent*iter) & ((Pack(1) << BitsPerComponent)-1));
}
}
auto operator<=>(const BitVec3&) const = default;
template<typename T2, size_t BitsPerComponent2>
operator BitVec3<T2, BitsPerComponent2>() const {
BitVec3<T, BitsPerComponent2> out;
for(size_t iter = 0; iter < N; iter++) {
out.set(iter, T2(std::make_unsigned_t<T2>(std::make_unsigned_t<T>(get(iter)))));
}
return out;
}
BitVec3 operator+(const BitVec3 &other) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) + other[iter];
return out;
}
BitVec3& operator+=(const BitVec3 &other) {
for(size_t iter = 0; iter < N; iter++)
get(iter) += other[iter];
Local16_u& operator=(const Key &key) {
X = key & 0xf;
Y = (key >> 4) & 0xf;
Z = (key >> 8) & 0xf;
return *this; return *this;
} }
Local4_u left() const { return Local4_u{uint8_t(uint16_t(X) >> 2), uint8_t(uint16_t(Y) >> 2), uint8_t(uint16_t(Z) >> 2)}; } BitVec3 operator+(const T value) const {
Local4_u right() const { return Local4_u{uint8_t(uint16_t(X) & 0b11), uint8_t(uint16_t(Y) & 0b11), uint8_t(uint16_t(Z) & 0b11)}; } BitVec3 out;
};
struct Local16 { for(size_t iter = 0; iter < N; iter++)
int8_t X : 4, Y : 4, Z : 4; out[iter] = get(iter) + value;
using Key = uint16_t; return out;
operator Key() const {
return Key(uint8_t(X)) | (Key(uint8_t(Y) << 4)) | (Key(uint8_t(Z)) << 8);
};
Local4_u left() const { return Local4_u{uint8_t(uint16_t(X) >> 2), uint8_t(uint16_t(Y) >> 2), uint8_t(uint16_t(Z) >> 2)}; }
Local4_u right() const { return Local4_u{uint8_t(uint16_t(X) & 0b11), uint8_t(uint16_t(Y) & 0b11), uint8_t(uint16_t(Z) & 0b11)}; }
};
struct Local256 {
int8_t X : 8, Y : 8, Z : 8;
auto operator<=>(const Local256&) const = default;
};
struct Local256_u {
uint8_t X : 8, Y : 8, Z : 8;
auto operator<=>(const Local256_u&) const = default;
};
struct Local4096 {
int16_t X : 12, Y : 12, Z : 12;
auto operator<=>(const Local4096&) const = default;
};
struct Local4096_u {
uint16_t X : 12, Y : 12, Z : 12;
auto operator<=>(const Local4096_u&) const = default;
};
struct GlobalVoxel {
int32_t X : 24, Y : 24, Z : 24;
auto operator<=>(const GlobalVoxel&) const = default;
};
struct GlobalNode {
int32_t X : 20, Y : 20, Z : 20;
using Key = uint64_t;
operator Key() const {
return Key(uint32_t(X)) | (Key(uint32_t(Y) << 20)) | (Key(uint32_t(Z)) << 40);
};
auto operator<=>(const GlobalNode&) const = default;
};
struct GlobalChunk {
int16_t X, Y, Z;
using Key = uint64_t;
operator Key() const {
return Key(uint16_t(X)) | (Key(uint16_t(Y)) << 16) | (Key(uint16_t(Z)) << 32);
};
operator glm::i16vec3() const {
return {X, Y, Z};
} }
auto operator<=>(const GlobalChunk&) const = default; BitVec3& operator+=(const T value) {
for(size_t iter = 0; iter < N; iter++)
get(iter) += value;
Local16_u toLocal() const { return *this;
return Local16_u(X & 0xf, Y & 0xf, Z & 0xf);
} }
BitVec3 operator-(const BitVec3 &other) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) - other[iter];
return out;
}
BitVec3& operator-=(const BitVec3 &other) {
for(size_t iter = 0; iter < N; iter++)
get(iter) -= other[iter];
return *this;
}
BitVec3 operator-(const T value) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) - value;
return out;
}
BitVec3& operator-=(const T value) {
for(size_t iter = 0; iter < N; iter++)
get(iter) -= value;
return *this;
}
BitVec3 operator*(const BitVec3 &other) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) * other[iter];
return out;
}
BitVec3& operator*=(const BitVec3 &other) {
for(size_t iter = 0; iter < N; iter++)
get(iter) *= other[iter];
return *this;
}
BitVec3 operator*(const T value) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) * value;
return out;
}
BitVec3& operator*=(const T value) {
for(size_t iter = 0; iter < N; iter++)
get(iter) *= value;
return *this;
}
BitVec3 operator/(const BitVec3 &other) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) / other[iter];
return out;
}
BitVec3& operator/=(const BitVec3 &other) {
for(size_t iter = 0; iter < N; iter++)
get(iter) /= other[iter];
return *this;
}
BitVec3 operator/(const T value) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) / value;
return out;
}
BitVec3& operator/=(const T value) {
for(size_t iter = 0; iter < N; iter++)
get(iter) /= value;
return *this;
}
BitVec3 operator>>(const auto offset) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out.set(iter, get(iter) >> offset);
return out;
}
BitVec3& operator>>=(const auto offset) {
for(size_t iter = 0; iter < N; iter++)
get(iter) >>= offset;
return *this;
}
BitVec3 operator<<(const auto offset) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) << offset;
return out;
}
BitVec3& operator<<=(const auto offset) {
for(size_t iter = 0; iter < N; iter++)
get(iter) <<= offset;
return *this;
}
BitVec3 operator|(const BitVec3 other) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) | other[iter];
return out;
}
BitVec3& operator|=(const BitVec3 other) {
for(size_t iter = 0; iter < N; iter++)
get(iter) |= other[iter];
return *this;
}
BitVec3 operator|(const T value) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) | value;
return out;
}
BitVec3& operator|=(const T value) {
for(size_t iter = 0; iter < N; iter++)
get(iter) |= value;
return *this;
}
BitVec3 operator&(const BitVec3 other) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) & other[iter];
return out;
}
BitVec3& operator&=(const BitVec3 other) {
for(size_t iter = 0; iter < N; iter++)
get(iter) &= other[iter];
return *this;
}
BitVec3 operator&(const T value) const {
BitVec3 out;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) & value;
return out;
}
BitVec3& operator&=(const T value) {
for(size_t iter = 0; iter < N; iter++)
get(iter) &= value;
return *this;
}
static constexpr size_t length() { return N; }
}; };
struct GlobalRegion { using bvec4i = BitVec3<int8_t, 2>;
int16_t X : 12, Y : 12, Z : 12; using bvec4u = BitVec3<uint8_t, 2>;
using bvec16i = BitVec3<int8_t, 4>;
using bvec16u = BitVec3<uint8_t, 4>;
using bvec256i = BitVec3<int8_t, 8>;
using bvec256u = BitVec3<uint8_t, 8>;
using bvec4096i = BitVec3<int8_t, 12>;
using bvec4096u = BitVec3<uint16_t, 12>;
using Key = uint64_t; using GlobalVoxel = BitVec3<int32_t, 24>;
operator Key() const { using GlobalNode = BitVec3<int32_t, 20>;
return Key(uint16_t(X)) | (Key(uint16_t(Y) << 12)) | (Key(uint16_t(Z)) << 24); using GlobalChunk = BitVec3<int16_t, 16>;
}; using GlobalRegion = BitVec3<int16_t, 14>;
using Object = BitVec3<int32_t, 32>;
auto operator<=>(const GlobalRegion&) const = default;
void fromChunk(const GlobalChunk &posChunk) {
X = posChunk.X >> 4;
Y = posChunk.Y >> 4;
Z = posChunk.Z >> 4;
}
GlobalChunk toChunk() const {
return GlobalChunk(uint16_t(X) << 4, uint16_t(Y) << 4, uint16_t(Z) << 4);
}
GlobalChunk toChunk(const Pos::Local16_u &posLocal) const {
return GlobalChunk(
(uint16_t(X) << 4) | posLocal.X,
(uint16_t(Y) << 4) | posLocal.Y,
(uint16_t(Z) << 4) | posLocal.Z
);
}
};
using Object = glm::i32vec3;
struct Object_t { struct Object_t {
// Позиции объектов целочисленные, BS единиц это один метр // Позиции объектов целочисленные, BS единиц это один метр
static constexpr int32_t BS = 4096, BS_Bit = 12; static constexpr int32_t BS = 4096, BS_Bit = 12;
static glm::vec3 asFloatVec(Object &obj) { return glm::vec3(float(obj.x)/float(BS), float(obj.y)/float(BS), float(obj.z)/float(BS)); } static glm::vec3 asFloatVec(const Object &obj) { return glm::vec3(float(obj[0])/float(BS), float(obj[1])/float(BS), float(obj[2])/float(BS)); }
static GlobalNode asNodePos(Object &obj) { return GlobalNode(obj.x >> BS_Bit, obj.y >> BS_Bit, obj.z >> BS_Bit); } static GlobalNode asNodePos(const Object &obj) { return (GlobalNode) (obj >> BS_Bit); }
static GlobalChunk asChunkPos(Object &obj) { return GlobalChunk(obj.x >> BS_Bit >> 4, obj.y >> BS_Bit >> 4, obj.z >> BS_Bit >> 4); } static GlobalChunk asChunkPos(const Object &obj) { return (GlobalChunk) (obj >> BS_Bit >> 4); }
static GlobalChunk asRegionsPos(Object &obj) { return GlobalChunk(obj.x >> BS_Bit >> 8, obj.y >> BS_Bit >> 8, obj.z >> BS_Bit >> 8); } static GlobalRegion asRegionsPos(const Object &obj) { return (GlobalRegion) (obj >> BS_Bit >> 8); }
}; };
} }
struct LightPrism {
uint8_t R : 2, G : 2, B : 2; using ResourceId_t = uint32_t;
/*
Bin привязывается к путю. Если по путю обновляется объект, пересчитывается его кеш и на клиентах обновляется
*/
enum class EnumBinResource {
Texture, Animation, Model, Sound, Font
}; };
// Идентификаторы на стороне клиента using BinaryResource = std::shared_ptr<const std::u8string>;
using TextureId_c = uint16_t;
using SoundId_c = uint16_t;
using ModelId_c = uint16_t;
using DefWorldId_c = uint8_t; // Двоичные данные
using DefVoxelId_c = uint16_t; using BinTextureId_t = ResourceId_t;
using DefNodeId_c = uint16_t; using BinAnimationId_t = ResourceId_t;
using DefPortalId_c = uint8_t; using BinModelId_t = ResourceId_t;
using WorldId_c = uint8_t; using BinSoundId_t = ResourceId_t;
using PortalId_c = uint8_t; using BinFontId_t = ResourceId_t;
using DefEntityId_c = uint16_t;
using EntityId_c = uint16_t; // Шаблоны использования бинарных ресурсов
using TextureId_t = ResourceId_t;
using AnimationId_t = ResourceId_t;
using ModelId_t = ResourceId_t;
using SoundId_t = ResourceId_t;
using FontId_t = ResourceId_t;
enum class EnumDefContent {
Voxel, Node, Generator, World, Portal, Entity, FuncEntitry
};
// Игровые определения
using DefVoxelId_t = ResourceId_t;
using DefNodeId_t = ResourceId_t;
using DefGeneratorId_t = ResourceId_t;
using DefWorldId_t = ResourceId_t;
using DefPortalId_t = ResourceId_t;
using DefEntityId_t = ResourceId_t;
using DefFuncEntityId_t = ResourceId_t;
// Контент, основанный на игровых определениях
using WorldId_t = ResourceId_t;
using PortalId_t = ResourceId_t;
// struct LightPrism {
// uint8_t R : 2, G : 2, B : 2;
// };
} }
@@ -174,12 +420,23 @@ using EntityId_c = uint16_t;
namespace std { namespace std {
#define hash_for_pos(type) template <> struct hash<LV::Pos::type> { std::size_t operator()(const LV::Pos::type& obj) const { return std::hash<LV::Pos::type::Key>()((LV::Pos::type::Key) obj); } }; template<typename T, size_t BitsPerComponent>
hash_for_pos(Local4_u) struct hash<LV::Pos::BitVec3<T, BitsPerComponent>> {
hash_for_pos(Local16_u) std::size_t operator()(const LV::Pos::BitVec3<T, BitsPerComponent>& obj) const {
hash_for_pos(Local16) std::size_t result = 0;
hash_for_pos(GlobalChunk) constexpr std::size_t seed = 0x9E3779B9;
hash_for_pos(GlobalRegion)
#undef hash_for_pos for (size_t i = 0; i < 3; ++i) {
T value = obj[i];
std::hash<T> hasher;
std::size_t h = hasher(value);
result ^= h + seed + (result << 6) + (result >> 2);
}
return result;
}
};
} }

View File

@@ -8,7 +8,7 @@ bool calcBoxToBoxCollide(const VecType vec1_min, const VecType vec1_max,
const VecType vec2_min, const VecType vec2_max, bool axis[VecType::length()] = nullptr const VecType vec2_min, const VecType vec2_max, bool axis[VecType::length()] = nullptr
) { ) {
using ValType = VecType::value_type; using ValType = VecType::Type;
ValType max_delta = 0; ValType max_delta = 0;
ValType result = 0; ValType result = 0;

View File

@@ -8,40 +8,19 @@
namespace LV::Server { namespace LV::Server {
using ResourceId_t = uint32_t;
// Двоичные данные
using BinTextureId_t = ResourceId_t;
using BinSoundId_t = ResourceId_t;
using BinModelId_t = ResourceId_t;
// Игровые определения
using DefWorldId_t = ResourceId_t;
using DefVoxelId_t = ResourceId_t;
using DefNodeId_t = ResourceId_t;
using DefPortalId_t = ResourceId_t;
using DefEntityId_t = ResourceId_t;
// Контент, основанный на игровых определениях
using WorldId_t = ResourceId_t;
// В одном регионе может быть максимум 2^16 сущностей. Клиенту адресуются сущности в формате <мир>+<позиция региона>+<uint16_t> // В одном регионе может быть максимум 2^16 сущностей. Клиенту адресуются сущности в формате <мир>+<позиция региона>+<uint16_t>
// И если сущность перешла из одного региона в другой, идентификатор сущности на стороне клиента сохраняется // И если сущность перешла из одного региона в другой, идентификатор сущности на стороне клиента сохраняется
using LocalEntityId_t = uint16_t; using EntityId_t = uint16_t;
using GlobalEntityId_t = std::tuple<WorldId_t, Pos::GlobalRegion, LocalEntityId_t>; using FuncEntityId_t = uint16_t;
using PortalId_t = uint16_t; using ClientEntityId_t = std::tuple<WorldId_t, Pos::GlobalRegion, EntityId_t>;
using MediaStreamId_t = uint16_t; using MediaStreamId_t = uint16_t;
using ContentBridgeId_t = uint16_t; using ContentBridgeId_t = ResourceId_t;
using PlayerId_t = uint32_t; using PlayerId_t = ResourceId_t;
/* /*
Сервер загружает информацию о локальных текстурах Сервер загружает информацию о локальных текстурах
Синхронизация часто используемых текстур?
Пересмотр списка текстур? Пересмотр списка текстур?
Динамичные текстуры? Динамичные текстуры?
@@ -66,13 +45,13 @@ struct ServerTime {
struct VoxelCube { struct VoxelCube {
DefVoxelId_t VoxelId; DefVoxelId_t VoxelId;
Pos::Local256_u Left, Right; Pos::bvec256u Left, Right;
auto operator<=>(const VoxelCube&) const = default; auto operator<=>(const VoxelCube&) const = default;
}; };
struct VoxelCube_Region { struct VoxelCube_Region {
Pos::Local4096_u Left, Right; Pos::bvec4096u Left, Right;
DefVoxelId_t VoxelId; DefVoxelId_t VoxelId;
auto operator<=>(const VoxelCube_Region&) const = default; auto operator<=>(const VoxelCube_Region&) const = default;
@@ -88,13 +67,13 @@ struct AABB {
Pos::Object VecMin, VecMax; Pos::Object VecMin, VecMax;
void sortMinMax() { void sortMinMax() {
Pos::Object::value_type left, right; Pos::Object::Type left, right;
for(int iter = 0; iter < 3; iter++) { for(int iter = 0; iter < 3; iter++) {
left = std::min(VecMin[iter], VecMax[iter]); left = std::min(VecMin[iter], VecMax[iter]);
right = std::max(VecMin[iter], VecMax[iter]); right = std::max(VecMin[iter], VecMax[iter]);
VecMin[iter] = left; VecMin.set(iter, left);
VecMax[iter] = right; VecMax.set(iter, right);
} }
} }
@@ -122,15 +101,19 @@ struct CollisionAABB : public AABB {
union { union {
struct { struct {
LocalEntityId_t Index; EntityId_t Index;
} Entity; } Entity;
struct { struct {
Pos::Local16_u Pos; FuncEntityId_t Index;
} FuncEntity;
struct {
Pos::bvec16u Pos;
} Node; } Node;
struct { struct {
Pos::Local16_u Chunk; Pos::bvec16u Chunk;
uint32_t Index; uint32_t Index;
DefVoxelId_t Id; DefVoxelId_t Id;
} Voxel; } Voxel;
@@ -197,9 +180,9 @@ struct VoxelCuboidsFuncs {
if (a.VoxelId != b.VoxelId) return false; if (a.VoxelId != b.VoxelId) return false;
// Проверяем, что кубы смежны по одной из осей // Проверяем, что кубы смежны по одной из осей
bool xAdjacent = (a.Right.X == b.Left.X) && (a.Left.Y == b.Left.Y) && (a.Right.Y == b.Right.Y) && (a.Left.Z == b.Left.Z) && (a.Right.Z == b.Right.Z); bool xAdjacent = (a.Right.x == b.Left.x) && (a.Left.y == b.Left.y) && (a.Right.z == b.Right.z) && (a.Left.z == b.Left.z) && (a.Right.z == b.Right.z);
bool yAdjacent = (a.Right.Y == b.Left.Y) && (a.Left.X == b.Left.X) && (a.Right.X == b.Right.X) && (a.Left.Z == b.Left.Z) && (a.Right.Z == b.Right.Z); bool yAdjacent = (a.Right.y == b.Left.y) && (a.Left.x == b.Left.x) && (a.Right.x == b.Right.x) && (a.Left.z == b.Left.z) && (a.Right.z == b.Right.z);
bool zAdjacent = (a.Right.Z == b.Left.Z) && (a.Left.X == b.Left.X) && (a.Right.X == b.Right.X) && (a.Left.Y == b.Left.Y) && (a.Right.Y == b.Right.Y); bool zAdjacent = (a.Right.z == b.Left.z) && (a.Left.x == b.Left.x) && (a.Right.x == b.Right.x) && (a.Left.y == b.Left.y) && (a.Right.y == b.Right.y);
return xAdjacent || yAdjacent || zAdjacent; return xAdjacent || yAdjacent || zAdjacent;
} }
@@ -209,13 +192,13 @@ struct VoxelCuboidsFuncs {
merged.VoxelId = a.VoxelId; merged.VoxelId = a.VoxelId;
// Объединяем кубы по минимальным и максимальным координатам // Объединяем кубы по минимальным и максимальным координатам
merged.Left.X = std::min(a.Left.X, b.Left.X); merged.Left.x = std::min(a.Left.x, b.Left.x);
merged.Left.Y = std::min(a.Left.Y, b.Left.Y); merged.Left.y = std::min(a.Left.y, b.Left.y);
merged.Left.Z = std::min(a.Left.Z, b.Left.Z); merged.Left.z = std::min(a.Left.z, b.Left.z);
merged.Right.X = std::max(a.Right.X, b.Right.X); merged.Right.x = std::max(a.Right.x, b.Right.x);
merged.Right.Y = std::max(a.Right.Y, b.Right.Y); merged.Right.y = std::max(a.Right.y, b.Right.y);
merged.Right.Z = std::max(a.Right.Z, b.Right.Z); merged.Right.z = std::max(a.Right.z, b.Right.z);
return merged; return merged;
} }
@@ -311,25 +294,25 @@ struct VoxelCuboidsFuncs {
inline void convertRegionVoxelsToChunks(const std::vector<VoxelCube_Region>& regions, std::vector<VoxelCube> *chunks) { inline void convertRegionVoxelsToChunks(const std::vector<VoxelCube_Region>& regions, std::vector<VoxelCube> *chunks) {
for (const auto& region : regions) { for (const auto& region : regions) {
int minX = region.Left.X >> 8; int minX = region.Left.x >> 8;
int minY = region.Left.Y >> 8; int minY = region.Left.y >> 8;
int minZ = region.Left.Z >> 8; int minZ = region.Left.z >> 8;
int maxX = region.Right.X >> 8; int maxX = region.Right.x >> 8;
int maxY = region.Right.Y >> 8; int maxY = region.Right.y >> 8;
int maxZ = region.Right.Z >> 8; int maxZ = region.Right.z >> 8;
for (int x = minX; x <= maxX; ++x) { for (int x = minX; x <= maxX; ++x) {
for (int y = minY; y <= maxY; ++y) { for (int y = minY; y <= maxY; ++y) {
for (int z = minZ; z <= maxZ; ++z) { for (int z = minZ; z <= maxZ; ++z) {
Pos::Local256_u left { Pos::bvec256u left {
static_cast<uint8_t>(std::max<uint16_t>((x << 8), region.Left.X) - (x << 8)), static_cast<uint8_t>(std::max<uint16_t>((x << 8), region.Left.x) - (x << 8)),
static_cast<uint8_t>(std::max<uint16_t>((y << 8), region.Left.Y) - (y << 8)), static_cast<uint8_t>(std::max<uint16_t>((y << 8), region.Left.y) - (y << 8)),
static_cast<uint8_t>(std::max<uint16_t>((z << 8), region.Left.Z) - (z << 8)) static_cast<uint8_t>(std::max<uint16_t>((z << 8), region.Left.z) - (z << 8))
}; };
Pos::Local256_u right { Pos::bvec256u right {
static_cast<uint8_t>(std::min<uint16_t>(((x+1) << 8)-1, region.Right.X) - (x << 8)), static_cast<uint8_t>(std::min<uint16_t>(((x+1) << 8)-1, region.Right.x) - (x << 8)),
static_cast<uint8_t>(std::min<uint16_t>(((y+1) << 8)-1, region.Right.Y) - (y << 8)), static_cast<uint8_t>(std::min<uint16_t>(((y+1) << 8)-1, region.Right.y) - (y << 8)),
static_cast<uint8_t>(std::min<uint16_t>(((z+1) << 8)-1, region.Right.Z) - (z << 8)) static_cast<uint8_t>(std::min<uint16_t>(((z+1) << 8)-1, region.Right.z) - (z << 8))
}; };
int chunkIndex = z * 16 * 16 + y * 16 + x; int chunkIndex = z * 16 * 16 + y * 16 + x;
@@ -346,12 +329,12 @@ inline void convertChunkVoxelsToRegion(const std::vector<VoxelCube> *chunks, std
for (int z = 0; z < 16; ++z) { for (int z = 0; z < 16; ++z) {
int chunkIndex = z * 16 * 16 + y * 16 + x; int chunkIndex = z * 16 * 16 + y * 16 + x;
Pos::Local4096_u left(x << 8, y << 8, z << 8); Pos::bvec4096u left(x << 8, y << 8, z << 8);
for (const auto& cube : chunks[chunkIndex]) { for (const auto& cube : chunks[chunkIndex]) {
regions.emplace_back( regions.emplace_back(
Pos::Local4096_u(left.X+cube.Left.X, left.Y+cube.Left.Y, left.Z+cube.Left.Z), Pos::bvec4096u(left.x+cube.Left.x, left.y+cube.Left.y, left.z+cube.Left.z),
Pos::Local4096_u(left.X+cube.Right.X, left.Y+cube.Right.Y, left.Z+cube.Right.Z), Pos::bvec4096u(left.x+cube.Right.x, left.y+cube.Right.y, left.z+cube.Right.z),
cube.VoxelId cube.VoxelId
); );
} }