Реформа ресурсов
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user