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

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 {
using EntityId_t = uint16_t;
using FuncEntityId_t = uint16_t;
struct GlobalTime {
uint32_t Seconds : 22 = 0, Sub : 10 = 0;
@@ -31,12 +34,12 @@ struct GlobalTime {
};
struct VoxelCube {
DefVoxelId_c VoxelId;
Pos::Local256_u Left, Size;
DefVoxelId_t VoxelId;
Pos::bvec256u Left, Size;
};
struct Node {
DefNodeId_c NodeId;
DefNodeId_t NodeId;
uint8_t Rotate : 6;
};
@@ -46,16 +49,16 @@ struct Chunk {
// Кубы вокселей в чанке
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 {
public:
// PosQuat
DefWorldId_c WorldId;
DefPortalId_c LastUsedPortal;
WorldId_t WorldId;
PortalId_t LastUsedPortal;
Pos::Object Pos;
glm::quat Quat;
static constexpr uint16_t HP_BS = 4096, HP_BS_Bit = 12;
@@ -70,10 +73,17 @@ public:
/* Интерфейс рендера текущего подключения к серверу */
class IRenderSession {
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 onDefModel(ModelId_c id, std::vector<std::byte> &&info) = 0;
virtual void onDefModelLost(const std::vector<ModelId_c> &&lost) = 0;
// Подгрузка двоичных ресурсов
virtual void onBinaryResourceAdd(std::unordered_map<EnumBinResource, std::unordered_map<ResourceId_t, BinaryResource>>) = 0;
virtual void onBinaryResourceLost(std::unordered_map<EnumBinResource, std::vector<ResourceId_t>>) = 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 onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) = 0;

View File

@@ -2,170 +2,416 @@
#include <cstdint>
#include <glm/ext.hpp>
#include <memory>
#include <type_traits>
#include <vector>
namespace LV {
namespace Pos {
struct Local4_u {
uint8_t X : 2, Y : 2, Z : 2;
template<typename T, size_t BitsPerComponent>
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;
operator Key() const {
return Key(X) | (Key(Y) << 2) | (Key(Z) << 4);
};
};
static constexpr auto getType() {
constexpr size_t bits = N*BitsPerComponent;
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 {
uint8_t X : 4, Y : 4, Z : 4;
T x : BitsPerComponent, y : BitsPerComponent, z : BitsPerComponent;
using Key = uint16_t;
operator Key() const {
return Key(X) | (Key(Y) << 4) | (Key(Z) << 8);
};
public:
BitVec3() = default;
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;
}
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)}; }
};
BitVec3 operator+(const T value) const {
BitVec3 out;
struct Local16 {
int8_t X : 4, Y : 4, Z : 4;
for(size_t iter = 0; iter < N; iter++)
out[iter] = get(iter) + value;
using Key = uint16_t;
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};
return out;
}
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 Local16_u(X & 0xf, Y & 0xf, Z & 0xf);
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 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 {
int16_t X : 12, Y : 12, Z : 12;
using bvec4i = BitVec3<int8_t, 2>;
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;
operator Key() const {
return Key(uint16_t(X)) | (Key(uint16_t(Y) << 12)) | (Key(uint16_t(Z)) << 24);
};
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;
using GlobalVoxel = BitVec3<int32_t, 24>;
using GlobalNode = BitVec3<int32_t, 20>;
using GlobalChunk = BitVec3<int16_t, 16>;
using GlobalRegion = BitVec3<int16_t, 14>;
using Object = BitVec3<int32_t, 32>;
struct Object_t {
// Позиции объектов целочисленные, BS единиц это один метр
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 GlobalNode asNodePos(Object &obj) { return GlobalNode(obj.x >> BS_Bit, obj.y >> BS_Bit, obj.z >> 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 asRegionsPos(Object &obj) { return GlobalChunk(obj.x >> BS_Bit >> 8, obj.y >> BS_Bit >> 8, obj.z >> BS_Bit >> 8); }
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(const Object &obj) { return (GlobalNode) (obj >> BS_Bit); }
static GlobalChunk asChunkPos(const Object &obj) { return (GlobalChunk) (obj >> BS_Bit >> 4); }
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 TextureId_c = uint16_t;
using SoundId_c = uint16_t;
using ModelId_c = uint16_t;
using BinaryResource = std::shared_ptr<const std::u8string>;
using DefWorldId_c = uint8_t;
using DefVoxelId_c = uint16_t;
using DefNodeId_c = uint16_t;
using DefPortalId_c = uint8_t;
using WorldId_c = uint8_t;
using PortalId_c = uint8_t;
using DefEntityId_c = uint16_t;
using EntityId_c = uint16_t;
// Двоичные данные
using BinTextureId_t = ResourceId_t;
using BinAnimationId_t = ResourceId_t;
using BinModelId_t = ResourceId_t;
using BinSoundId_t = ResourceId_t;
using BinFontId_t = ResourceId_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 {
#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); } };
hash_for_pos(Local4_u)
hash_for_pos(Local16_u)
hash_for_pos(Local16)
hash_for_pos(GlobalChunk)
hash_for_pos(GlobalRegion)
#undef hash_for_pos
template<typename T, size_t BitsPerComponent>
struct hash<LV::Pos::BitVec3<T, BitsPerComponent>> {
std::size_t operator()(const LV::Pos::BitVec3<T, BitsPerComponent>& obj) const {
std::size_t result = 0;
constexpr std::size_t seed = 0x9E3779B9;
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
) {
using ValType = VecType::value_type;
using ValType = VecType::Type;
ValType max_delta = 0;
ValType result = 0;

View File

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